页数:56页文件大小:355.9 KB来源: 数据结构与算法ppt课件
本课件讲解线性表的定义、特性与抽象数据类型,重点展开顺序表示与链式表示两类存储结构,包含初始化、插入、删除、按值查找与有序表合并等算法,最后以一元多项式的表示与相加作为综合应用。
第二章线性表
线性结构的特点
内容提要:
第一节线性表的定义
1.1线性表的定义
O数据项->记录->文件……………好商业120.0王磊1003好商业145.2李明1002面积类别使用情况地块号户主记录数据项文件
1.2线性表特性
1.3线性表相关概念
1.4抽象数据类型线性表的定义
1.5线性表的复杂操作
算法2.2两非递减有序线性表归并
while(i<=La_len){//La表还有元素,将剩余元素顺序插入LcGetElem(La,i++,ai);ListInsert(Lc,++k,ai);
第二节线性表的顺序表示和实现
2.1顺序表示的含义
内存状态a1a2…ai…anbb+(n-1)L…b+(i-1)L…b+L存储地址1n…i…2元素序号2.2顺序存储结构示意图
2.3顺序存储结构的高级语言定义
算法2.3:线性表初始化 StatusInitList_Sq(SqList&L){ L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType)) if(!L.elem)exit(OVERFLOW);L.length=0;L.Listsize=LIST_INIT_SIZE;returnOK }算法2.4:在第i个元素之前插入元素e StatusListInsert_Sq(SqList&L,inti,ElemTypee){ if(i<1||i>L.length+1)returnERROR;if(L.length>=L.Listsize){if(!newbase)exit(OVERFLOW);//新基址L.Listsize+=LISTINCREMENT;} q<-p新空间0p+1e第i个元素i-1L.length-1pq= &(L.elem[i-1])//q为插入位置(第i个元素之前)
算法2.5:删除第i个元素并返回给ee第i个元素 StatusListDelete_Sq(SqList&L,inti,ElemType&e){ if( (i<1)||(i>L.length))returnERROR;p= &(L.elem[i-1])//p为删除元素的位置 e=*p; q = L.elem+L.length-1;for(++p; p<=q; ++p)*(p-1)=*p//被删除元素之后的元素左移 --L.length; returnOK; L.elemp->q0i-1L.length-1 }2.4顺序存储结构的讨论
算法2.6:在线性表中查找第1个值与e满足compare()的元素的位序 intLocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)){ i =1; p=L.elem; while(i<=L.length&&!(*compare)(*p++,e))++i; if(i<L.length)returni; elsereturn0; } 基本操作为两元素之间的比较 时间复杂度为O(L.length)先比较*p和e,然后p++算法2.7:顺序表的合并 VoidMergeList_Sq(SqListLa,SqListLb,SqList_Lc&Lc){ pa=La.elem; pb=Lb.elem; Lc.Listsize=Lc.length=La.length+Lb.length; pc=Lc.elem=(ElemType*)malloc(Lc.listsize*sizeof(ElemType)); if(!Lc.elem)exit(OVERFLOW);pa_last=La.elem+La.length-1; pb_last=Lb.elem+Lb.length-1;while(pa<=pa_last&&pb<=pb_last){//归并if(*pa<=*pb)*pc++ =*pa++;else*pc++=*pb++
2.5顺序存储结构的特点
第三节线性表的链式表示和实现
3.1链式表示的含义
3.2线性链表
3.2.1单链表的链式存储结构 TypedefstructLNode{ ElemTypedata; StructLnode*next; } LNode,*LinkList 单链表任意两个元素的存储位置没有固定的关系 但每个元素的位置都包含在其直接前驱结点的信息之中 若p->data=ai,则p->next->data=ai+1 查找第i个元素必须从头指针开始算法2.8GetElem函数在单链表中的实现 StatusGetElem_L(LinkListL,inti,ElemType&e){ p=L->next; j=1;while(p&&j<i){++j; } if(!p||j>i)returnERROR;e=p->data; returnOK; } 第31页:算法2.9单链表插入
算法2.9插入函数在单链表中的实现 StatusListInsert_L(LinkList&L,inti,ElemTypee){p=L; j =0;while(p&&j<i-1){ p= p->next; ++j}if(!p||j>i-1)returnERROR;s=(LinkList)malloc(sizeof(LNode));s->data=e; s->next= p->next;p->next=s; returnOK; } 算法的时间复杂度为O(n)spP->next
第32页:算法2.10单链表删除
算法2.10删除函数在单链表中的实现 StatusListDelete_L(LinkList&L,inti,ElemType&e){p=L; j =0;while(p->next&&j<i-1){ p=p->next; ++j }if(!(p->next) ||j>i-1)returnERROR;q=p->next; p->next= q->next;e=q->data; free(q); returnOK; } 算法的时间复杂度为O(n)P(i-1)qq->next
第33页:3.2.2单链表的一维数组表示
3.2.2单链表的一维数组表示 #defineMAXSIZE1000//链表的最大长度 typedefstruct{ ElemTypeintdata; cur; } Component,SLinkList[MAXSIZE]; 适合不便设“指针”的高级程序设计语言中使用链表结构 数组的第0号元素可看成是头结点,其指针指向第一个结点 需要预先分配一个较大的空间,但插入、删除操作不需移动元素
第34页:静态链表示例
实例:静态链表示例1002ZHAO123QIAN34SUN45LI56ZHOU67WU78ZHENG80WANG91012ZHAO3QIAN4SUN9LI6ZHOU8WU8ZHENG0WANG5SHI线性表:(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)在LI后插入SHI、删除ZHENG012345678910插入SHI修改后12ZHAO3QIAN4SUN9LI6ZHOU7WU8ZHENG0WANG5SHI修改前
第35页:3.2循环链表与特点
3.2循环链表与特点
- 最后一个结点的指针指向头结点,整个链形成一个环
- 可以从任何一个结点出发找到其他点
- 头指针作为循环判断条件(p->next=head)
- 两个线性表合并时,一个表的表尾和另一个表的表头连接非空表H空表H
第36页:3.3双向链表
3.3双向链表
- 目的:克服单链表的单向寻查的缺点
- 有两个指针域:一个指向直接后继,另一个指向直接前驱L空表非空表LABC前驱指针数据元素后继指针结点
第37页:3.3.1双向链表的C描述
3.3.1双向链表的C描述 TypedefstructDuLNode{ ElemTypedata; StructDuLNode*prior; StructDuLNode*next; } DuLNode,*DuLinkList; 若d为指向某一结点的指针,则有d->next->prior=d->prior->next=d 插入和删除操作需要同时修改两个方向上的指针
第38页:3.3.2双向链表的插入操作
3.3.2双向链表的插入操作 StatusListInsert_DuL(DuLinkList&L,inti,ElemTypee){if(!(p=GetElemP_Dul(L,i)))//在L中确定第i个元素的位置指针 returnERROR; if(!(s=(DuLinkList)malloc(sizeof(DuLNOde))))returnERROR; s->data=e; s->prior=p->prior; p->prior->next=s; s->next=p; p->prior=s; returnOK } sp
第39页:3.3.3双向链表的删除操作
3.3.3双向链表的删除操作 StatusListDelete_DuL(DuLinkList&L,inti,ElemType&e){e =p->data; p->prior->next =p->next; p->next->prior=p->prior; free(p); returnOK } ep
第40页:3.4带头结点的线性链表定义
3.4带头结点的线性链表定义
- 链表尽管在插入、删除时不需要移动元素
- 但在求链表长度时不如顺序存储结构
- typedefstructLnode{typedefstruct{ElemTypedata;StructLnode*next;Linkhead,tail;intlen;
- }*Link,*position;}LinkList;
- 基本操作见P37-38
- 存储头结点和最后一个结点的指针,操作方便
- 记录线性表数据元素的个数
第41页:带头结点线性链表的基本操作
带头结点的线性链表基本操作见P37-38
- StatusMakeNode(Link&p,ElemTypee);//分配由p指向的值为e的结点,并返回OK,否则返回ERROR
- StatusInitList(LinkList&L);//构造一个空的线性链表
- StatusDestroyList(LinkList&L);//销毁线性链表L
- StatusInsFirst(Linkh,Links);//h为指向线性链表的头结点,将s所指的结点插入在第一个结点之前
- StatusAppend(LinkList&L,Links);//将s所指的一串结点连接在线性链表L的最后一个结点
- StatusRemove(LinkList&L,Link&q);//删除线性链表L的尾结点,并以q返回
- Status LocatePos(LinkList L, inti, Link&p);//返回p指示线性链表L中第I个结点的位置并返回OK,否则i值不合法时返回ERROR
- ………………………………..
第42页:算法2.20带头结点单链表插入
算法2.20带头结点的单链线性表的插入StatusListInsert_L(LinkList&L,inti,ElemTypee){ if(!LocatePos(L,i-1,h))returnERROR;//h为L的第i-1个结点,也是从第i个结点开始链表的头结点 if( !MakeNode(s,e))returnERROR;InsFirst(h,s);//将s插入以h(第i-1个结点)为头结点线性表的第1个结点之前 } hsi-1i
第43页:算法2.21两非递减链表归并
算法2.21两非递减线性链表归并成非递减表
- StatusMergeList_L(LinkList&La,LinkList&Lb,LinkList&Lc){
- if(!InitList(Lc))returnERROR;//初始化
- ha=GetHead(La);hb=GetHead(Lb);//获得指向线性表的头结点
- pa=NextPos(ha);pb=NextPos(hb);//指向各自的第1个结点
- while(!Empty(La)&&!(Empty(Lb)){//La,Lb均非空a=GetCurElem(pa);b=GetCurElem(pb);//a,b为两表当前元素if((*compare)(a,b)<=0{//比较a,b大小,a<=bDelFirst(ha,q);Append(Lc,q);pa=NextPos(La,pa); }//删除ha指向链表的头结点并返回给q,然后追加到Lc表后面,La结点后移else{
第44页:算法2.21续:剩余结点链接
else{DelFirst(hb,q);Append(Lc,q);pb=NextPos(Lb,pb);}
- }//while
- if(!Empty(La))Append(Lc,pa);//链接La剩余结点
- elseAppend(Lc,pb);//链接Lb剩余结点
- freeNode(ha);freeNode(hb);//释放La,Lb的头结点
- returnOK;
- }//La,Lb归并为Lc,均为非递减
第45页:3.5链式存储结构的特点
3.5链式存储结构的特点
- 优点:
- 插入、删除元素时不需要移动元素
- 缺点:
- 逻辑上相邻,物理位置不一定相邻
- 不能随机存取表中元素,需要依次查找
- 求线性表的长度时不如顺序存储结构方便,需要逐个结点搜索计算,或设置带头结点的线性链表
第46页:第四节一元多项式的表示及相加
第四节一元多项式的表示及相加
第47页:4.1一元多项式及其线性表表示
4.1一元多项式Pn(x)及其操作
- 一个一元多项式Pn(x)P(x)ppxpx2...pxnn012n
- n+1个系数,用线性表P来表示P= (p0,p1,p2, …,pn)
- 另一个一元多项式Qm(x)Q= (q0,q1,q2, …,qm)
- 假设m<n,执行Rn(x)=Pn(x)+ Qm(x)操作时,可用线性表R表示R=(p0+q0,p1+q1,…,pm+qm,pm+1,…,pn)
- 可以利用顺序存储结构定义P,Q,R
第48页:稀疏多项式的存储问题
问题:当多项式次数很高且变化较大时,最大长度难以确定,很难用顺序存储结构表示,例如S(x)13x100002x20000
- 要用长度为20001的线性表来表示,但只有三个非零元素,浪费内存空间
- 可以采用存储系数项和指数项的方法节省存储空间,对如下一元m次多项式meee...px122mPn(x)p1xpx
- 可以采用一个长度为m的每个元素有两个数据项的线性表表示((p1,e1),(p2,e2),…,(pm,em))
- 该线性表可以用顺序存储结构和链式存储结构来表示,前者适合运算后不改变多项式的系数和指数的情况,否则采用后者
第49页:4.2抽象数据类型一元多项式的定义
4.2抽象数据类型一元多项式的定义
- }ADTPolynomial
- ADTPolynomial{
- 数据对象:D={ai|aiElemset,i=1,2,…,m,m0Elemset中每个元素包含系数实数和指数整数}
- 数据关系:R={<ai-1,ai>|ai,ai+1D,且ai-1的指数小于ai的指数,i=2,…,n}
- 基本操作:
- CreatePolyn(&P,m)//输入m项的系数和指数,建立一元多项式
- DestroyPolyn(&p)//消毁一元多项式
- PolynLength(P)//返回一元多项式P中的项数
- AddPolyn(&Pa,&Pb)//多项式相加
- SubtractPolyn(&Pa,&Pb)//多项式相减,并销毁Pb
- …………
第50页:4.3一元多项式ADT的实现
4.3抽象数据类型Polynomial的实现
- typedefstruct{Floatcoef;//系数Intexpn;//指数
- }term,ElemType;
- typedefLinkListpolynomial;//用带表头结点的有序链表表示多项式
- 基本操作:CreatPolyn();//创建PolynLength();//长度DestroyPolyn();//销毁AddPolyn();//相加SubtractPolyn();//相减MultiPolyn();//相乘
第51页:算法2.22建立有序链表P
算法2.22建立有序链表P
- voidCreatPolyn(Polynomial&P,intm){
- InitList(P);h=GetHead(P);
- e.coef=0.0;e.expn=-1;SetCurElem(h,e);
- //设置表头数据
- for(i=1; i<=m;++i){//依次输入m个非零项Scanf(e.coef,e.expn;)if(!LocateElem(P,e,q,(*cmp))){//当前P中不存在该项的指数if(MakeNode(s,e))InsFirst(q,s);//生成结点并插入}
- }
- }//输入m项的系数和指数,建立表示一元多项式的有序链表P
第52页:算法2.23多项式相加
VoidAddPolyn(polynomial&Pa,polynomial&Pb){
- ha=GetHead(Pa);hb= GetHead(Pb);//获得指向线性表的头结点
- qa=NextPos(ha);qb=NextPos(hb);//指向各自的第1个结点
- while(!Empty(Pa)&&!(Empty(Pb)){//Pa,Pb均非空
- a=GetCurElem(qa);b=GetCurElem(qb);//a,b为两表当前元素
- switch(*cmp(a,b)){
- case–1://Pa当前指数小,Pa指针往后移
- ha=qa;qa=NextPos(Pa,qa);break;
- case0://Pa与Pb当前指数相等,相加
- Sum=a.coef+b.coef;
- if(sum!=0.0){//不为零时修改
- SetCurElem(qa,sum);ha=qa;}算法2.23多项式相加
第53页:算法2.23续:指数比较处理
续算法2.23
- else{//为零时删除
- DelFirst(ha,qa);FreeNode(qa);}
- DelFirst(hb,qb);FreeNode(qb);qb=NextPos(Pb,hb);//删除Pb的当前结点,并移向下一个结点
- qa=NextPos(Pa,ha);break;//Pa结点后移
- case1://Pb当前指数小,Pb当前结点插入Pa
- DelFirst(hb,qb);InsFirst(ha,qb);//删除Pb当前结点,将Pb结点内容插入Pa
- qb=NextPos(Pb,hb);//Pb往后一个结点移
- }
- }
- if(!Empty(Pb))Append(Pa,qb);//链接Pb剩余结点
- FreeNode(hb);//释放Pb的头结点
- }//求Pa=Pa+Pb
第54页:本章重点
本章重点
- 线性表的表示形式:顺序、链式
- 链式表示的各种形式
- 两种形式的优缺点
- 存储结构
- 操作方法:合并、插入、删除
- 了解一元多项式表示与实现,如何节省空间
第55页:习题(一)
习题:
- 1、在一个长度为n的线性链表中第i个元素(1in)之前插入一个元素时,需向后移动n-i+1个元素。
- 2、在一个长度为n的线性链表中删除第i个元素(1in)时,需向前移动n-i个元素。
- 3、单链表是线性表的链式存储结构。
- 4、在一个双链表中,每个结点有两个指针域,一个指向前驱结点,另一个指向后继结点。
- 5、在一个单链表中p所指结点之后插入一个s所指结点时,应执行s->next=p->next和p->next=s的操作。
- 6、在单链表中,插入或删除一个结点元素时,仅需要修改指针而不需要移动元素。
第56页:习题(二)
7、非空的循环单链表head的尾结点(有p所指向)满足条件p->next=head。
- 8、在一个具有n个结点的有序单链表中,插入一个新结点并仍然有序的时间复杂度为O(n)。
- 9、给定有n个元素的向量,建立一个有序单链表的时间复杂度是O(n2)。
- 10、有一个单链表(不同结点的数据域可能相同),其头指针为head,编写一个函数计算数据域为x的结点个数。
- 11、已知一个单链表,编写一个函数将该单链表复制一个拷贝。习题:
下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}