第三章 线性表的链式存储结构教案
- 格式:doc
- 大小:97.00 KB
- 文档页数:9
南昌航空大学实验报告课程名称:数据结构实验名称:实验二:线性表的链式存储结构班级: 080611 学生姓名:赖凌学号: 08061101指导教师评定:签名:题目:设计并实现以下算法:给出用单链表存储多项式的结构,利用后接法生成多项式的单链表结构,实现两个多项式相加的运算,并就地逆置相加后的多项式链式。
一、需求分析⒈实现两张线性表的链式存储,合并及删除值相同元素的操作。
⒉在演示过程序中,用户敲击键盘,即可观看演示结果。
⒊程序执行的命令包括:(1)构造线性链表A (2)构造线性链表B (3)求两张表的并(4)删除C中值相同的元素二、概要设计⒈为实现上述算法,需要线性表的抽象数据类型:ADT LinkList List {数据对象:D={a i:|a i∈ElemSet,i=1…n,n≥0}数据关系:R1={<a i-1,a i>|a i-1,a i∈D,i=2,…n≥0}基本操作:Status InitList( LinkList &L)//操作结果:构造一个空的线性链表L。
Status MakeNode ( Link &p, ElemType e );// 分配由p指向的值为e 的结点,并返回OK;若分配失败,则返回ERRORStatus Append (LinkList &L,Link s);//将指针s所指(彼此以指针相链接)的一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点Status ListEmpty(LinkList L);//若线性链表L为空表,则返回TRUE,否则返回ERROR。
Int ListLength(LinkList L);//返回线性链表中L最后一个结点的位置。
ElemType GetCurElem(Link p);//已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值Position GetHead (LinkList L);//返回线性链表L中头结点的位置Position GetLast( LInkList L);//返回线性链表L中最后一个结点的位置}ADT LinkList2. 本程序有三个模块:⑴主程序模块void main(){初始化;{接受命令;显示结果;}}⑵线性链表单元模块:实现线性链表抽象数据类型;⑶结点结构单元模块:定义线性链表中的结点结构。
1.掌握线性链表、单链表、静态链表的概念。
2.掌握线性链表的表示及实现方法。
➢ 教学重点:线性链表之单链表的表示及实现方法。
➢ 教学难点: 线性链表的概念。
➢ 授课内容2.3 线性表的链式存储结构由于顺序表的存贮特点是用物理上的相邻实现了逻辑上的相邻,它要求用连续的存储单元顺序存储线性表中各元素,因此,对顺序表插入、删除时需要通过移动数据元素来实现,影响了运行效率。
本节介绍线性表链式存储结构,它不需要用地址连续的存储单元来实现,因为它不要求逻辑上相邻的两个数据元素物理上也相邻,它是通过“链”建立起数据元素之间的逻辑关系来,因此对线性表的插入、删除不需要移动数据元素。
2.3.1单链表链表是通过一组任意的存储单元来存储线性表中的数据元素的,那么怎样表示出数据元素之间的线性关系呢?为建立起数据元素之间的线性关系,对每个数据元素a i ,除了存放数据元素的自身的信息 a i 之外,还需要和a i 一起存放其后继 a i+1 所在的存贮单元的地址,这两部分信息组成一个“结点”,结点的结构如图2.6 所示,每个元素都如此。
存放数据元素信息的称为数据域,存放其后继地址的称为指针域。
因此n 个元素的线性表通过每个结点的指针域拉成了一个“链子”,称之为链表。
因为每个结点中只有一个指向后继的指针,所以称其为单链表。
链表是由一个个结点构成的,结点定义如下: typedef struct node{ datatype data;struct node *next;} LNode ,*LinkList ; 定义头指针变量: LinkList H ;如图2.7是线性表 (a 1,a 2,a 3,a 4,a 5,a 6,a 7,a 8) 对应的链式存储结构示意图。
第四讲 线性表的链式存储结构图2.6 单链表结点结构 data next当然必须将第一个结点的地址160 放到一个指针变量如 H 中,最后一个结点没有后继, 其指针域必需置空,表明此表到此结束,这样就可以从第一个结点的地址开始“顺藤摸瓜”,找到每个结点。
石家庄经济学院实验报告学院: 信息工程学院专业: 计算机信息工程学院计算机实验中心制一 实验内容1.进一步熟悉C 语言的上机环境,掌握C 语言的基本结构。
2.会定义线性表的链式存储结构。
3.熟悉对单链表的一些基本操作(建表、插入、删除等)和具体的函数定义。
二 实验目的掌握链式存储结构的特点,了解、掌握并实现单链表的常用的基本算法。
三 需求设计线性表抽象数据类型的描述及实现ADT List{数据对象: {|,,,,,0}i i D a a ElemSet i 12n n =∈=≥数据关系: {,|,,,,}i 1i i 1i R a a a a D i 2n --=<>∈=基本操作:构造一个空的线性表L InitList();销毁线性表L DestroyList();将L 重置为空表 ClearList();判断L 是否为空 ListEmpty();求表长 ListLength();查找元素 LocateElem();求前驱 PriorElem();求后继 NextElem();插入元素ListInsert();删除元素ListDelete();元素调用visit()函数ListTraverse(L,visit())}ADT List;程序具体实现要求:1.创建一个线性表2.能输出所有数据元素3.能求线性表长度4.能插入删除元素5.能查找元素6.能求元素的前驱和后继7.用户操作界面如下:*********************************** 1. 构造线性表* 2. 插入元素* 3. 删除元素* 4. 查找元素* 5. 显示表长* 6. 求后继* 7. 求前驱* 8. 输出所有元素* 0. 结束程序运行*********************************** 请输入您的选择(0,1,...,8):四详细设计步骤4:上机编程与调试主程序如下:#include "stdafx.h"#include "stdio.h"#include "LinkList0515.h"#include "user.h"#include "Fun.h"int main(int argc, char* argv[]){CLinkList0515 L;LinkList l;int flag,flag1=0,loc,e,next_e,pre_e;printf("\n**************************************"); printf("\n* 1. 构造单链表");printf("\n* 2. 插入元素");printf("\n* 3. 删除元素");printf("\n* 4. 查找元素");printf("\n* 5. 显示表长");printf("\n* 6. 求后继");printf("\n* 7. 求前驱");printf("\n* 8. 输出所有元素");printf("\n* 0. 结束程序运行");printf("\n**************************************");while(1){printf("\n请输入您的选择(0,1,...,8): ");scanf("%d",&flag);switch(flag){case 0:++flag1;break;case 1:if(OK==L.InitList_L(l))printf("\n成功完成单链表初始化操作!\n");elseprintf("\n操作失败,内存溢出!\n");break;case 2:printf("\n 请输入插入元素的位序,值(空格隔开): ");scanf("%d %d",&loc,&e);if(ERROR==L.ListInsert_L(l,loc,e))printf("\n操作失败,可能是插入位序不合理!\n");elseprintf("\n成功完成操作!\n");L.ListTraverse_L(l,DisplayData);break;case 3:printf("\n 请输入被删除元素的位序: ");scanf("%d",&loc);if(ERROR==L.ListDelete_L(l,loc,e))printf("\n操作失败,可能是位序不合理!\n");else{ printf("\n元素 %d 成功被删除!\n",e);L.ListTraverse_L(l,DisplayData);}break;case 4:printf("\n 请输入待查找的元素的值: ");scanf("%d",&e);loc=L.LocateElem_L(l,e,compare);if(!loc)printf("\n表中不存在元素 %d !\n",e);elseprintf("\n找到了,元素 %d 在表中的位置是: %d \n",e,loc);break;case 5:printf("\n表长为: %d \n",L.ListLength_L(l));break;case 6:printf("\n 请输入元素的值: ");scanf("%d",&e);if(ERROR==L.NextElem_L(l,e,next_e))printf("\n表中元素 %d 没有后继!\n",e);elseprintf("\n表中元素%d 的后继是: %d\n",e,next_e);break;case 7:printf("\n 请输入元素的值: ");scanf("%d",&e);if(ERROR==L.PriorElem_L(l,e,pre_e))printf("\n表中元素 %d 没有前驱!\n",e);elseprintf("\n表中元素%d 的前驱是: %d \n",e,pre_e);break;case 8:L.ListTraverse_L(l,DisplayData);break;default:break;} //switchif(flag1==1) break;}//whileprintf("\n结束!\n\n\n");return 0;}运行结果如下:图3.1五实验总结1. 基本掌握线性表链式存储结构的特点;2. 基本掌握单链表的常用的基本操作算法;3. 通过线性表的抽象数据类型的学习,进一步掌握抽象数据类型的定义方法;4. 对于同一个线性表,用顺序结构和链式存储结构实现,算法也不同;从而可知,逻辑结构依赖于物理结构;。
实验一:设线性表L1和L2分别代表集合A和B,试设计算法求A 和B的并集C,并用线性表L3代表集合C。
实验二:设计一个一元多项式计算器,要求能够:①输入并建立多项式;②输出多项式;③执行两个多项式相加;④执行两个多项式相减。
1.实验目的:掌握线性表的链式存储结构设计与基本操作的实现。
2.实验内容与要求:⑴定义线性表的链式存储表示;⑵基于所设计的存储结构实现线性表的基本操作;⑶编写一个主程序对所实现的线性表进行测试;3.数据结构设计实验一:逻辑结构:线性结构存储结构:链式存储结构实验二:逻辑结构:线性结构存储结构:链式存储结构4.算法设计实验一#include<stdio.h>#include<stdlib.h>typedef int datatype;typedef struct node{datatype data; //结点值struct node *next; //存储下一个结点的地址}LinkList;LinkList *CREATLISTF(LinkList *L,int n) {int num,i;LinkList *head,*s,*r;head=L;r=head;head->next=NULL;printf("请输入集合中的元素(由小到大):\n");for(i=0;i<n;i++){scanf("%d",&num);s=(LinkList*)malloc(sizeof(LinkList));s->data=num;r->next=s; //链接到表中r=s; //r指向新的尾结点}r->next=NULL;return head;}LinkList *merge(LinkList *L1,LinkList *L2){LinkList *L3,*pa,*pb1,*pb2,*pc;L3=(LinkList*)malloc(sizeof(LinkL ist));//申请结点L3->next=NULL; //初始化链表L3pa=L1->next; //pa是链表L1的工作指针,指向第一个结点pb1=pb2=L2->next; //pb1是链表L2的工作指针,指向第一个结点pc=L3; //pc是链表L3的工作指针,指向头结点while(pa && pb1) //L1和L2均非空if(pa->data<pb1->data){//L1中元素插入L3pc->next=pa; pc=pa; pa=pa->next;}else if(pa->data>pb1->data){//L2中元素插入L3pc->next=pb1; pc=pb1; pb1=pb1->next;}else{pc->next=pa;pc=pa;pa=pa->next; pb1=pb2=pb1->next;}if(pa) pc->next=pa; //若pa未到尾,将pc指向paelse pc->next=pb1; //若pb1未到尾,将pc指向pb1return(L3);}void display(LinkList *L){LinkList *head;head=L->next;do{printf("%d\t",head->data);head=head->next;}while(head!=NULL);}void main(){int an,bn;LinkList *L1,*L2,*L3;L1=(LinkList*)malloc(sizeof(LinkL ist));L2=(LinkList*)malloc(sizeof(LinkL ist));printf("\n请输入集合A中元素的个数:\n");scanf("%d",&an);*L1=*CREATLISTF(L1,an);printf("集合A的元素为:\n");display(L1);printf("\n请输入集合B中元素的个数:\n");scanf("%d",&bn);*L2=*CREATLISTF(L2,bn);printf("集合B的元素为:\n");display(L2);L3=merge(L1,L2);printf("交集为:\n");display(L3);}实验二typedef struct node{ int coef;int exp;struct node *next;}polynode;polynode *Creat1polynode();polynode *Creat2polynode();polynode *subpolynode(polynode *ha,polynode *hb);polynode *addpolynode(polynode *ha,polynode *hb);#include<stdlib.h>#include<stdio.h>int main(){ polynode *ha,*hb,*hc,*hd,*p;ha=Creat1polynode();p=ha->next;printf("输出多项式A:");if(p->exp==0)printf("%d",p->coef);elseprintf("%dx^%d",p->coef,p->exp); p=p->next;while(p!=NULL){ if(p->coef>0){ printf("+");printf("%dx^%d",p->coef,p->exp);}elseprintf("%dx^%d",p->coef,p->exp);p=p->next;}printf("\n");hb=Creat2polynode();p=hb->next;printf("输出多项式B:");if(p->exp==0)printf("%d",p->coef);else printf("%dx^%d",p->coef,p->exp); p=p->next;while(p!=NULL){ if(p->coef>0){ printf("+");printf("%dx^%d",p->coef,p->exp);}elseprintf("%dx^%d",p->coef,p->exp);p=p->next;}printf("\n");hc=subpolynode(ha,hb);p=hc->next;printf("输出差多项式:");if(p->exp==0)printf("%d",p->coef);elseprintf("%dx^%d",p->coef,p->exp); p=p->next;while(p!=NULL){ if(p->coef>0){ printf("+");printf("%dx^%d",p->coef,p->exp);}elseprintf("%dx^%d",p->coef,p->exp);p=p->next;}printf("\n");hd=addpolynode(ha,hb);p=hd->next;printf("输出和多项式:");if(p->exp==0)printf("%d",p->coef);elseprintf("%dx^%d",p->coef,p->exp);p=p->next;while(p!=NULL){ if(p->coef>0){ printf("+");printf("%dx^%d",p->coef,p->exp);}elseprintf("%dx^%d",p->coef,p->exp);p=p->next;}printf("\n");}polynode *Creat1polynode(){ polynode *s,*r,*ha;int m,n;ha=(polynode*)malloc(sizeof(polynode));r=ha;printf("请输入系数m和指数n: ");scanf("%d,%d",&m,&n);while(m!=0){ s=(polynode *)malloc(sizeof(polynode));s->coef=m;s->exp=n;r->next=s;r=s;printf("请输入系数m和指数n: ");scanf("%d,%d",&m,&n);}r->next=NULL;return(ha);}polynode *Creat2polynode(){ polynode *s,*r,*hb;int m,n;hb=(polynode*)malloc(sizeof(polynode));r=hb;printf("请输入系数m和指数n: "); scanf("%d,%d",&m,&n);while(m!=0) { s=(polynode *)malloc(sizeof(polynode));s->coef=m;s->exp=n;r->next=s;r=s;printf("请输入系数m和指数n: ");scanf("%d,%d",&m,&n);}r->next=NULL;return(hb);}polynode *subpolynode(polynode *ha,polynode *hb){ polynode *hc,*p,*q,*s,*r;int sum;p=ha->next;q=hb->next;hc=(polynode*)malloc(sizeof(polynode));r=hc;while(p!=NULL&&q!=NULL){ if(p->exp==q->exp){ sum=p->coef-q->coef;if(sum!=0){ s=(polynode *)malloc(sizeof(polynode));s->coef=sum;s->exp=p->exp;r->next=s;r=s;}p=p->next;q=q->next;}else{ if(p->exp<q->exp){ s=(polynode *)malloc(sizeof(polynode));s->coef=p->coef;s->exp=p->exp;r->next=s;r=s;p=p->next;}else{ s=(polynode *)malloc(sizeof(polynode));s->coef=0-q->coef;s->exp=q->exp;r->next=s;r=s;q=q->next;}}}while(p!=NULL){ s=(polynode *)malloc(sizeof(polynode));s->coef=p->coef;s->exp=p->exp;r->next=s;r=s;p=p->next;}while(q!=NULL){ s=(polynode *)malloc(sizeof(polynode));s->coef=0-q->coef;s->exp=q->exp;r->next=s;r=s;q=q->next;}r->next=NULL;return(hc);}polynode *addpolynode(polynode *ha,polynode *hb){ polynode *p,*q,*pre,*r;int sum;p=ha->next;q=hb->next;pre=ha;while(p!=NULL&&q!=NULL){ if(p->exp<q->exp){ pre->next=p;pre=pre->next;p=p->next;}else if(p->exp==q->exp) { sum=p->coef+q->coef;if(sum!=0){ p->coef=sum;pre->next=p;pre=pre->next;p=p->next;r=q;q=q->next;free(r);}else{ r=p->next;free(p);p=r;r=q->next;free(q);q=r;}}else{ pre->next=q;pre=pre->next;q=q->next;}}while(p!=NULL){ pre->next=p;pre=pre->next;p=p->next;}while(q!=NULL){ pre->next=q;pre=pre->next;q=q->next;}pre->next=NULL;return(ha);}5.测试结果实验一实验二。
实验报告三线性表的链式存储一、实验目的:(1)掌握单链表的基本操作的实现方法。
(2)掌握循环单链表的基本操作实现。
(3)掌握两有序链表的归并操作算法。
二、实验内容:(请采用模板类及模板函数实现)1、线性表链式存储结构及基本操作算法实现[实现提示] (同时可参见教材p64-p73页的ADT描述及算法实现及ppt)函数、类名称等可自定义,部分变量请加上学号后3位。
也可自行对类中所定义的操作进行扩展。
所加载的库函数或常量定义:(1)单链表存储结构类的定义:template <class datatype> class LinkList; //前视定义,便于使用友元template <class datatype>class Node{ friend class LinkList<datatype>; //友元类private:datatype data;Node<datatype> *next; //此处<datatype>也可以省略}template <class datatype>class LinkList{public:LinkList( ); //建立只有头结点的空链表LinkList(datatype a[ ], int n); //建立有n个元素的单链表~LinkList(){} //析构函数,释放整个链表空间int Length(); //求单链表的长度datatype Get(int i); //取单链表中第i个结点的元素值void Insert(int i, datatype x); //在单链表中第i个位置插入元素值为x的结点 void destroy() //在单链表中删除所有的结点void PrintList( ); //遍历单链表,按序号依次输出各元素int Empty() //判断表是否为空private:Node<datatype> *head; //单链表的头指针};(2)初始化带头结点空单链表构造函数实现输入:无前置条件:无动作:初始化一个带头结点的空链表输出:无后置条件:头指针指向头结点。