收藏 分享(赏)

第二章线性表(第2版).ppt

上传人:11xg27ws 文档编号:8222848 上传时间:2019-06-15 格式:PPT 页数:98 大小:630KB
下载 相关 举报
第二章线性表(第2版).ppt_第1页
第1页 / 共98页
第二章线性表(第2版).ppt_第2页
第2页 / 共98页
第二章线性表(第2版).ppt_第3页
第3页 / 共98页
第二章线性表(第2版).ppt_第4页
第4页 / 共98页
第二章线性表(第2版).ppt_第5页
第5页 / 共98页
点击查看更多>>
资源描述

1、1,第二章 线性表,2.1 线性表 2.2 顺序表 2.3 单链表 2.4 线性链表的其它变形 2.5 多项式,2,2.1 线性表 (Linear List),一、线性表的概念线性表是 n (0) 个数据元素的有限序列,记为:L =(a1, a2, , an) L是表名,ai 是表中数据元素,n 是表长度 线性表的第一个表项称为表头,最后一个表项称为表尾; 原则上讲,线性表中表元素的数据类型可以不相同。为简单起见,假定各元素类型相同;,3,线性表的特点 线性表是一个有限的序列,每两个相邻表项之间都有直接前驱和后继关系; 除第一个元素外,其他每一个元素有一个且仅有一个直接前驱;除最后一个元素外,

2、其它每一个元素有一个且仅有一个直接后继。 直接前驱和直接后继描述了结点之间的逻辑关系(即邻接关系)。,4,二、线性表的抽象基类,template class LinearList public:LinearList(); /构造函数LinearList(); /析构函数virtual int Size() const = 0; /求表最大体积virtual int Length() const = 0; /求表长度virtual int Search(T,5,virtual bool Insert(int i, T 线性表的存储表示有两种:顺序存储方式和链表存储方式; (体会逻辑结构和存储结构

3、),6,2.2 顺序表 (Sequential List),一、顺序表的定义和特点 定义:把线性表中的所有表项按照其逻辑顺序依次存储到从计算机存储中指定位置开始的一块连续的存储空间中。 特点 所有元素的逻辑先后顺序与其物理存放顺序一致;(逻辑结构&存储结构) 对顺序表中的所有项,既可以进行顺序访问,也可以进行随机访问;,7,可利用一维数组描述存储结构。,8,二、顺序表的类及其操作,描述顺序表的存储表示有两种方式:静态方式和动态方式。,#define maxSize 100 typedef int T; typedef struct T datamaxSize; int n; SeqList;,

4、typedef int T; typedef struct T *data; int maxSize, n; SeqList;,9,顺序表(SeqList)类的定义。,#include #include #include “LinearList.h“ const int defaultSize = 100; template class SeqList: public LinearList private:T *data; /存放数组int maxSize; /最大可容纳表项的项数int last; /当前已存表项数(从0开始)void reSize(int newSize); /改变数组空间

5、大小,10,public:SeqList( int sz = defaultSize ); /构造函数SeqList( SeqList/i从1开始计数,11,bool Insert(int i, T x); /插入x在i项之后bool Remove(int i, T,12,顺序表的构造函数,template SeqList:SeqList(int sz) if (sz 0) maxSize = sz; last= -1;data = new TmaxSize; /创建存储数组if (data = NULL) /动态分配失败 cerr “存储分配错误!“endl; exit(1); ;,13,t

6、emplate SeqList:SeqList ( SeqList,复制构造函数,14,GetData和SetData函数 template T SeqList:GetData(int i) const /i从1开始计数 if (ilast+1) cerr“Invalid index of seqlist“endl;exit(0); else return datai-1; ,template void SeqList:SetData(int i, T ,15,reSize函数 template void SeqList:reSize(int newSize) /私有函数:扩充顺序表的存储数组

7、空间大小,新数组的元素个数为newSize if(newSize=0)cerr“无效的数组大小”endl; return;if(newSize!=maxSize)T* newarray=new TnewSize;if (newarray=NULL) cerr“存储分配错误”endl; exit(1);/int n= ( newSize=maxSize ) ? newSize : maxSize;int n=last+1;T* srcptr=data; T* destptr=newarray;while(n-) *destptr+=*srcptr+;delete data; data=newar

8、ray; maxSize=newSize;/end of if /end of void,16,顺序搜索图示,顺序表的搜索算法,17,18,template int SeqList:search(T /搜索失败 ,搜索算法,19,表项的定位,templateclass T int SeqListT:Locate(int i) const /定位函数:函数返回第i(1=i=1ast+1)个表项的位置,否则函数返回0,表示定位失败。if (i1 & ilast+1) return i;else return 0; ,20,表项的插入,25 34 57 16 48 09 63 ,0 1 2 3 4

9、5 6 7,data,50,插入 x,25 34 57 50 16 48 09 63 ,0 1 2 3 4 5 6 7,data,50,i,i=3 x=50,21,表项的插入算法,template bool SeqList:Insert (int i, T x) /将新元素x插入到表中下标为i (0ilast+1) 的表项中。 /插入成功,返回true;否则返回false;若i=0,插入第一个元素if (last = maxSize-1) return false; /表满if (i last+1) return false; /参数i不合理for (int j = last; j = i;

10、j-) /依次后移dataj+1 = dataj; datai = x; /插入last+; /扩容,否则无法访问最后元素return true; /插入成功 ;,22,表项的删除,x=16,23,表项的删除算法,template bool SeqList:Remove (int i, T,/参考书思考另外插入删除方法 P51,24,template void SeqList:input() coutlast; last-;if (lastdatai; ,输入输出操作和赋值操作,不好,25,template void SeqList:output() cout“顺序表当前元素最后位置为:“la

11、stendl;for ( int i=0; i=last; i+)cout“#“i+1“:“dataiendl; ,26,template SeqList SeqList:operator =(SeqList ,27,搜索成功的平均比较次数 pi 是搜索第 i 项的概率ci 是找到时的比较次数 若搜索概率相等,则,搜索性能分析,三、顺序表的性能分析,28,插入算法的性能分析,在表中第 i 个位置后插入,从datai 到data n 成块后移,移动n-i项。 考虑所有插入位置,相等插入概率时,从 1 到 n+1,平均移动次数为:,29,删除算法的性能分析,删除第 i 个表项,需将第 i+1 项到

12、第 n 项全部前移,需前移的项数为:n-i; 考虑表中所有可能删除位置,相等删除概率时,平均移动元素个数为:,30,顺序表的应用:集合的“并”运算,void Union ( SeqList /插入到第n个表项之后,四、顺序表的应用,31,void Intersection ( SeqList ,顺序表的应用:集合的“交”运算,32,顺序表的优缺点,优点缺点,无需为表示结点间的逻辑关系而增加额外的存储空间,存储利用率高; 可以方便地随机存取表中的任一结点,存取速度快。,表中插入新元素或删除无用元素时,为了保持其他元素的相对次序不变,平均需要移动一半元素;存储空间分配问题;,33,思考,利用数组或

13、顺序表方式来组织数据结构: 优点:存储利用率高;存储速度快 缺点:元素个数动态增长;插入删除需多次移动;n个长度变化的有序表,最大可能长度会大量浪费空间链表:适用于插入或删除频繁,存储空间需求不定的情形,34,一、单链表的概念单链表的一个存储结点(node)有两个域:一个线性表(a1,a2,an)的单链表结构: 特点: 结点的逻辑顺序与物理顺序可以不一致 表可扩充,2.3 单链表,35,单链表的存储映像,free,(a) 可利用存储空间,a0,a2,a1,a3,free,first,(b) 经过一段运行后的单链表结构,36,二、单链表的类定义,通常使用两个类,协同表示单链表:链表的结点(lin

14、knode)类;链表(list)类;一个链表包含了零个或多个结点,因此一个类型为List的对象包含有零个或多个类型为LinkNode的对象。定义方式:,复合方式嵌套方式继承方式结构方式,37,(1)复合类 class List; /List类的前视声明class LinkNode /结点类 friend class List; /链表类为其友元类private:int data; /结点数据域 LinkNode * link; /结点指针 ;class List /链表类 private:LinkNode *first ; /表头指针public: ;,38,(2)嵌套类 class List

15、 /嵌套方式 private:class LinkNode /嵌套链表结点类 public:int data; LinkNode *link; ;LinkNode *first; /表头指针public:/链表操作; /如LinkNode类为public,可用List:LinkNode LN; /嵌套类使用请参考C+ Primer Plus(第五版)P547,39,(3)基类和派生类 class LinkNode /链表结点类 protected:int data; LinkNode * link; ;class List : public class LinkNode private:Lin

16、kNode *first; /表头指针public:/链表操作;,40,(4)用struct定义LinkNode类struct LinkNode /链表结点类 int data; LinkNode * link; ;class List private:LinkNode *first; /表头指针,链表中的结点属于/链表私有,别人无法访问;,41,在C+中struct与class的区别在于:在struct中,默认的访问级别是public。若在struct内部自始至终缺省访问级别,则所有的成员都在公共接口中。而在class中,默认的访问级别是private。除此之外,struct与class是等

17、价的。,42,(1)单链表的插入算法 第一种情况:在链表最前端插入(能否颠倒)newnode-link = first ; first = newnode;,(插入前) (插入后),二、单链表中的插入与删除操作 (注意:先操作再断开),43,(插入前) (插入后),第二种情况:在链表中间插入newnode-link = current-link; current-link = newnode;,44,第三种情况:在链表末尾插入newnode-link = current-link; current-link = newnode;,(插入前) (插入后),注意二、三情况的操作统一,45,单链表的

18、插入算法,bool List:Insert(int i, int,46,第一种情况: 删除表中第一个元素,在单链表第一个结点处删除,(2)单链表的删除算法,del=first; first=first-link; delete del;,47,第二种情况: 删除表中或表尾元素,在表中或表尾删除含ai的结点,ai-1,ai-1,ai,ai,ai+1,ai+1,删除前,删除后,del=cur-link; cur-link=del-link; delete del;,48,bool List:Remove (int i, int,删除算法,49,小结: 实现单链表的插入和删除算法,不需要移动元素,只

19、需修改结点指针,比顺序表方便。 情况复杂,要专门讨论空表和在表头插入的特殊情形。 寻找插入或删除位置只能沿着链顺序检测。,50,四、带表头结点的单链表,表头结点位于表的最前端,本身不带数据,仅标志表头。 设置表头结点的目的是统一空表与非空表的操作,简化链表操作的实现。,非空表,an-1,a1,first,51,在非空表的附加头结点后面的插入,newnode-link = current-link; current-link = newnode;,first,newnode,first,newnode,插入,current,current,在空表的附加头结点后面的插入,插入(非空表、空表、表中、

20、表尾统一操作),52,del = current-link;current-link = del-link;delete del;,(非空表),(空表),first,first,first,0,first,0,current,del,current,del,删除(删除第一个结点后非空、空;表中、表尾统一),53,五、单链表的模板类,类模板将类的数据成员和成员函数设计得更完整、更灵活。 类模板更易于复用。 在单链表的类模板定义中,增加了表头结点。,54,用模板定义的单链表类,template /定义在“LinkedList.h” struct LinkNode /链表结点类的定义 T data;

21、 /数据域LinkNode *link; /链指针域LinkNode(LinkNode *ptr = NULL ) link = ptr; /构造函数LinkNode(const T,55,template class List : public LinearList /单链表类定义 protected:LinkNode *first; /表头指针public:List() first = new LinkNode; /构造函数List(const T /计算链表的长度,56,LinkNode *getHead() const return first; LinkNode *Search(T

22、x); /搜索含x元素LinkNode *Locate(int i); /定位第i个元素bool getData(int i, T ,57,template void List:makeEmpty() LinkNode *q;while (first-link != NULL) q = first-link; /保存被删结点first-link = q-link; /从链上摘下该结点delete q; /删除 ;,链表置空算法(保留表头结点),58,template int List : Length ( ) const ListNode *p = first-link;int count =

23、 0; while ( p != NULL ) /逐个结点检测 p = p-link; count+; return count; ,59,求单链表的长度的算法,60,单链表的搜索算法,template LinkNode *List:Search(T x) /在表中搜索含数据x的结点, 搜索成功时函数返 /该结点地址; 否则返回NULL。LinkNode *current = first-link;while ( current != NULL ,61,单链表的定位算法,template LinkNode *List:Locate ( int i ) /函数返回表中第 i 个元素的地址。若i

24、*current = first; int k = 0;while ( current != NULL /试分析i=0情况,62,getData和setData函数,template bool List :getData(int i, T ,template void List :setData(int i, T ,63,单链表的插入算法,template bool List:Insert (int i, T,64,单链表的删除算法,template bool List:Remove (int i, T,65,单链表的输出函数,template void List:output() LinkN

25、ode *current = first-link;while ( current !=NULL ) coutdatalink; ,66,前插法建立单链表,主要步骤:从一个空表开始,重复读入数据: 生成新结点,将读入数据存放到新结点的数据域中; 将该新结点插入到链表的前端,直到读入结束符为止;,单链表的输入函数,67,template void List :inputFront (T endTag) LinkNode *newNode; T val;makeEmpty();cinval;while (val != endTag) newNode = new LinkNode(val);if (

26、 newNode = NULL ) cerrlink = first-link; /插在表前端first-link = newNode;cin val; ;,68,后插法建立单链表,每次将新结点插到链表的表尾; 设置一个尾指针 last,总是指向表中最后一个结点,新结点插在它的后面; 尾指针 last 初始时置为指向表头结点地址。,69,template void List :inputRear ( T endTag ) LinkNode *newNode, *last; T val;makeEmpty(); cinval; last = first;while (val != endTag)

27、 newNode = new LinkNode(val);if ( newNode = NULL ) cerrlink = newNode; /插在表前端last = newNode;cin val; ,70,重载函数:赋值操作,template Listreturn *this; /返回操作对象 /见单链表的程序演示,71,power类及其操作:,#include class power double x;int e;double mul;public:power (double val, int exp);double get_power() return mul; ;,power:pow

28、er(double val,int exp) x = val; e = exp;mul = 1.0;if ( exp =0 ) return;for (; exp0; exp- ) mul = mul*x; ,main() power pwr(1.5, 2);coutpwr.get_power()“n”; ,72,一、循环链表 (Circular List),1.循环链表的概念 循环链表是单链表的变形。 循环链表的最后一个结点的 link 指针不为 NULL,而是指向了表的前端。 循环链表的特点是:只要知道表中某一结点的地址,就可搜寻到所有其他结点的地址。,2.4 线性链表的其它变形,循环链表

29、的示意图,73,带表头结点的循环链表,74,template struct CircLinkNode /循环链表结点类定义 T data;CircLinkNode *link;CircLinkNode ( CircLinkNode *next =NULL ) link = next; CircLinkNode ( T d, CircLinkNode *next =NULL ) data = d; link = next; ;,2.循环链表类定义,75,template /循环链表类定义 class CircList : public LinearList private: CircLinkNo

30、de *first, *last; /头指针, 尾指针 public: CircList(const T/返回表头结点地址,76,void setHead ( CircLinkNode *p );/设置表头结点地址CircLinkNode *Search ( T x ); /搜索CircLinkNode *Locate ( int i ); /定位T *getData ( int i ); /提取void setData ( int i, T x ); /修改bool Insert ( int i, T循环链表与单链表的操作实现,最主要的不同就是扫描到链尾,遇到的不是NULL,而是表头。,77

31、,搜索不成功,循环链表的搜索算法,搜索25,78,循环链表的搜索算法,template CircListNode * CircList:Search( T x ) /在链表中从头搜索其数据值为 x 的结点 current = ;while ( ,first-link,current != first,79,3.用循环链表求解约瑟夫问题,约瑟夫问题的提法:n 个人围成一个圆圈,首先第 1 个人从 1 开始,一个人一个人顺时针报数, 报到第 m 个人,令其出列。然后再从下一 个人开始,从 1 顺时针报数,报到第 m 个人,再令其出列,如此下去, 直到圆圈中只剩一个人为止。此人即为优胜者。 用不带表

32、头结点的循环链表来组织。,80,例如 n = 8 m = 3,81,n = 8 m = 3,82,求解Josephus问题的算法,template void Josephus(CircList,83,void main() CircList clist; int i, n m; cout n m;for (i = 1; i = n; i+ ) clist.insert(i); /约瑟夫环 Josephus(clist, n, m); /解决约瑟夫问题 ,84,三、双向链表,1.双向链表的概念 双向链表是指在前驱和后继方向都能遍历的线性链表。 双向链表每个结点结构:,85,结点指向 p = p-

33、lLink-rLink = p-rLink-lLink,双向链表通常采用带表头结点的循环链表形式。,非空表,空表,86,2.带附加头结点的双向循环链表类的定义,template struct DblNode /双链表结点类定义 T data; /链表结点数据 DblNode *lLink, *rLink; /前驱、后继指针 DblNode(DblNode *left = NULL, DblNode *right=NULL) lLink = left; rLink = right; /构造函数 DblNode ( T value, DblNode *left = NULL, DblNode *r

34、ight = NULL ) data = value; lLink = left; rLink = right; ;,87,template class DblList /链表类定义 public:DblList ( T uniqueVal ); /构造函数,建立附加头结点DblList (); /析构函数:释放所用存储int Length() const; /计算双链表的长度bool IsEmpty() return first-rlink = first; DblNode *getHead()const return first; void setHead(DblNode *ptr) fi

35、rst = ptr; DblNode *Search (const T/在链表中按后继方向寻找等于给定值x的结点,88,DblNode *Locate ( int i, int d ); /在链表中定位序号为i(0)的结点, d=0按前驱/方向,d0按后继方向bool Insert ( int i, const T,89,template DblList:DblList( T uniqueVal )/构造函数:建立双向循环链表的附加头结点,它/包含了一个用于某些特定情况的值; first = new DblNode (uniqueVal);if ( first=NULL) cerrrLink

36、= first-lLink = first; ;,90,template int DblList:Length() const DblNode *cur = first-rLink; int count=0; while ( ) cur=cur-rLink; count+; return count; ,cur != first,91,3. 双向循环链表的搜索、插入和删除算法,双向循环链表的搜索算法,92,template DblNode *DblList:Search (const T,93,template DblNode *DblList:Locate ( int i, int d )

37、/在链表中定位序号为i(0)的结点, d=0按前驱方 /向,d0按后继方向 if (first-rlink = first | i=0 ) return first;DblNode *current;if (d = 0) current = first-lLink;else current = first-rLink;for (int j=1; jlLink;else current = current-rLink;if ( current ! = first ) return current;else return NULL;,双向循环链表的定位算法,94,双向循环链表的插入算法,newNo

38、de-rLink = current-rLink; current-rLink = newNode; newNode-rLink-lLink = newNode; newNode-lLink = current;,非空表:,95,空表:,first,后插入25,current,newNode,25,first,current,newNode-rLink = current-rLink current-rLink = newNode; newNode-rLink -lLink = newNode; newNode-lLink = current;,96,template bool DblList

39、:Insert ( int i, T x, int d ) DblNode *current = Locate(i,d);if ( current = NULL ) return false; /插入失败DblNode *newNd = new DblNode(x);if (d = 0) /前驱方向:插在第i个结点左侧 newNd-lLink = current-lLink; /链入lLink链current-lLink = newNd;newNd-lLink-rLink = newNd; /链入rLink链newNd-rLink = current; else /后继方向:插在第i个结点后面

40、 newNd-rLink = current-rLink; /链入rLink链current-rLink = newNd;newNd-rLink-lLink = newNd; /链入lLink链newNd-lLink = current; return true; /插入成功 ;,97,删除48,双向循环链表的删除算法,first,first,非空表,31,48,15,current,31,15,current,current-rLink-lLink = current-lLink; current-lLink-rLink = current-rLink;,98,双向循环链表的删除算法,template bool DblList:Remove( int i, T,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报