版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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),一、顺序表的定义和特点 定义:把线性表中的所有表项按照其逻辑顺序依次存储到从计算机存储中指定位置开始的一块连续的存储空间中。 特点 所有元素的逻辑先后顺序与其物理存放顺序一致;(逻辑结构 typedef struct T datamaxSize; int n; SeqList;,typedef int T; typedef struct T *data; int maxSize, n; SeqList;,9,顺序表(SeqList)类的定义。,#include #include #include LinearList.h
4、const int defaultSize = 100; template class SeqList: public LinearList private: T *data; /存放数组 int maxSize; /最大可容纳表项的项数 int last; /当前已存表项数(从0开始) void reSize(int newSize);/改变数组空间大小,10,public: SeqList( int sz = defaultSize ); /构造函数 SeqList( SeqList/i从1开始计数,11,bool Insert(int i, T x); /插入x在i项之后 bool Re
5、move(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,template SeqList:SeqList ( SeqList,复制构造函数,14,GetData和SetData函数 template T SeqList:GetData(int i) const /i从1开始计数 if (ilast
6、+1) cerrInvalid index of seqlistendl; exit(0); else return datai-1; ,template void SeqList:SetData(int i, T,15,reSize函数 template void SeqList:reSize(int newSize) /私有函数:扩充顺序表的存储数组空间大小,新数组的元素个数为newSize if(newSize=0)cerr“无效的数组大小”endl; return; if(newSize!=maxSize) T* newarray=new TnewSize; if (newarray=
7、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=newarray; maxSize=newSize; /end of if /end of void,16,顺序搜索图示,顺序表的搜索算法,17,18,template int SeqList:search(T /搜索失败 ,搜索算法,1
8、9,表项的定位,templateclass T int SeqListT:Locate(int i) const /定位函数:函数返回第i(1=i=1ast+1)个表项的位置,否则函数返回0,表示定位失败。 if (i1 /表满 if (i last+1) return false; /参数i不合理 for (int j = last; j = i; j-) /依次后移 dataj+1 = dataj; datai = x; /插入 last+; /扩容,否则无法访问最后元素 return true; /插入成功 ;,22,表项的删除,x=16,23,表项的删除算法,template bool
9、 SeqList:Remove (int i, T,/参考书思考另外插入删除方法 P51,24,template void SeqList:input() coutlast;last-; if (lastdatai; ,输入输出操作和赋值操作,不好,25,template void SeqList:output() cout顺序表当前元素最后位置为:lastendl; for ( int i=0; i=last; i+) cout#i+1:dataiendl; ,26,template SeqList SeqList:operator =(SeqList ,27,搜索成功的平均比较次数 pi
10、是搜索第 i 项的概率 ci 是找到时的比较次数 若搜索概率相等,则,搜索性能分析,三、顺序表的性能分析,28,插入算法的性能分析,在表中第 i 个位置后插入,从datai 到data n 成块后移,移动n-i项。 考虑所有插入位置,相等插入概率时,从 1 到 n+1,平均移动次数为:,29,删除算法的性能分析,删除第 i 个表项,需将第 i+1 项到第 n 项全部前移,需前移的项数为:n-i; 考虑表中所有可能删除位置,相等删除概率时,平均移动元素个数为:,30,顺序表的应用:集合的“并”运算,void Union ( SeqList /插入到第n个表项之后 ,四、顺序表的应用,31,voi
11、d Intersection ( SeqList ,顺序表的应用:集合的“交”运算,32,顺序表的优缺点,优点 缺点,无需为表示结点间的逻辑关系而增加额外的存储空间,存储利用率高; 可以方便地随机存取表中的任一结点,存取速度快。,表中插入新元素或删除无用元素时,为了保持其他元素的相对次序不变,平均需要移动一半元素; 存储空间分配问题;,33,思考,利用数组或顺序表方式来组织数据结构: 优点:存储利用率高;存储速度快 缺点:元素个数动态增长;插入删除需多次移动;n个长度变化的有序表,最大可能长度会大量浪费空间 链表:适用于插入或删除频繁,存储空间需求不定的情形,34,一、单链表的概念 单链表的一
12、个存储结点(node)有两个域: 一个线性表(a1,a2,an)的单链表结构: 特点: 结点的逻辑顺序与物理顺序可以不一致 表可扩充,2.3 单链表,35,单链表的存储映像,free,(a) 可利用存储空间,a0,a2,a1,a3,free,first,(b) 经过一段运行后的单链表结构,36,二、单链表的类定义,通常使用两个类,协同表示单链表: 链表的结点(linknode)类; 链表(list)类; 一个链表包含了零个或多个结点,因此一个类型为List的对象包含有零个或多个类型为LinkNode的对象。 定义方式:,复合方式 嵌套方式 继承方式 结构方式,37,(1)复合类 class L
13、ist; /List类的前视声明 class LinkNode /结点类 friend class List; /链表类为其友元类 private: int data; /结点数据域 LinkNode * link; /结点指针 ; class List /链表类 private: LinkNode *first ; /表头指针 public: ;,38,(2)嵌套类 class List /嵌套方式 private: class LinkNode /嵌套链表结点类 public: int data; LinkNode *link; ; LinkNode *first; /表头指针 publi
14、c: /链表操作 ; /如LinkNode类为public,可用List:LinkNode LN; /嵌套类使用请参考C+ Primer Plus(第五版)P547,39,(3)基类和派生类 class LinkNode /链表结点类 protected: int data; LinkNode * link; ; class List : public class LinkNode private: LinkNode *first; /表头指针 public: /链表操作 ;,40,(4)用struct定义LinkNode类 struct LinkNode/链表结点类 int data; Li
15、nkNode * link; class List private: LinkNode *first; /表头指针,链表中的结点属于 /链表私有,别人无法访问 ;,41,在C+中struct与class的区别在于:在struct中,默认的访问级别是public。若在struct内部自始至终缺省访问级别,则所有的成员都在公共接口中。而在class中,默认的访问级别是private。除此之外,struct与class是等价的。,42,(1)单链表的插入算法 第一种情况:在链表最前端插入(能否颠倒) newnode-link = first ; first = newnode;,(插入前) (插入后
16、),二、单链表中的插入与删除操作 (注意:先操作再断开),43,(插入前) (插入后),第二种情况:在链表中间插入 newnode-link = current-link; current-link = newnode;,44,第三种情况:在链表末尾插入 newnode-link = current-link; current-link = newnode;,(插入前) (插入后),注意二、三情况的操作统一,45,单链表的插入算法,bool List:Insert(int i, int,46,第一种情况: 删除表中第一个元素,在单链表第一个结点处删除,(2)单链表的删除算法,del=first
17、; 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,小结: 实现单链表的插入和删除算法,不需要移动元素,只需修改结点指针,比顺序表方便。 情况复杂,要专门讨论空表和在表头插入的特殊情形。 寻找插入或删除位置只能沿着链顺序检测。,50,四、带表头结点的单链表,表头结点位于表的最前端
18、,本身不带数据,仅标志表头。 设置表头结点的目的是统一空表与非空表的操作,简化链表操作的实现。,非空表,an-1,a1,first,51,在非空表的附加头结点后面的插入,newnode-link = current-link; current-link = newnode;,first,newnode,first,newnode,插入,current,current,在空表的附加头结点后面的插入,插入(非空表、空表、表中、表尾统一操作),52,del = current-link; current-link = del-link; delete del;,(非空表),(空表),first,fi
19、rst,first,0,first,0,current,del,current,del,删除(删除第一个结点后非空、空;表中、表尾统一),53,五、单链表的模板类,类模板将类的数据成员和成员函数设计得更完整、更灵活。 类模板更易于复用。 在单链表的类模板定义中,增加了表头结点。,54,用模板定义的单链表类,template /定义在“LinkedList.h” struct LinkNode /链表结点类的定义 T data; /数据域 LinkNode *link; /链指针域 LinkNode(LinkNode *ptr = NULL ) link = ptr; /构造函数 LinkNod
20、e(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 x);/搜索含x元素 LinkNode *Locate(int i);/定位第i个元素 bool getData(int i, T ,57,template
21、 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 = 0; while ( p != NULL ) /逐个结点检测 p = p-link; count+; return count; ,59,求单链表
22、的长度的算法,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 *current = first; int k = 0; while ( current != NULL /试分析i=0情况,62,getDat
23、a和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() LinkNode *current = first-link; while ( current !=NULL ) coutdatalink; ,66,前
24、插法建立单链表,主要步骤: 从一个空表开始,重复读入数据: 生成新结点,将读入数据存放到新结点的数据域中; 将该新结点插入到链表的前端,直到读入结束符为止;,单链表的输入函数,67,template void List :inputFront (T endTag) LinkNode *newNode; T val; makeEmpty(); cinval; while (val != endTag) newNode = new LinkNode(val); if ( newNode = NULL ) cerrlink = first-link; /插在表前端 first-link = newN
25、ode; cin val; ;,68,后插法建立单链表,每次将新结点插到链表的表尾; 设置一个尾指针 last,总是指向表中最后一个结点,新结点插在它的后面; 尾指针 last 初始时置为指向表头结点地址。,69,template void List :inputRear ( T endTag ) LinkNode *newNode, *last; T val; makeEmpty(); cinval;last = first; while (val != endTag) newNode = new LinkNode(val); if ( newNode = NULL ) cerrlink =
26、 newNode; /插在表前端 last = newNode; cin val; ,70,重载函数:赋值操作,template List return *this; /返回操作对象 /见单链表的程序演示,71,power类及其操作:,#include class power double x; int e; double mul; public: power (double val, int exp); double get_power() return mul; ;,power:power(double val,int exp) x = val; e = exp; mul = 1.0; i
27、f ( 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 线性链表的其它变形,循环链表的示意图,73,带表头结点的循环链表,74,template struct CircLinkNod
28、e /循环链表结点类定义 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: CircLinkNode *first, *last; /头指针, 尾指针 public: CircList(con
29、st 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,搜索不成功,循环链表的搜索算法,搜索25,78,循环链表的搜索算法,templ
30、ate CircListNode * CircList:Search( T x ) /在链表中从头搜索其数据值为 x 的结点 current = ; while ( ,first-link,current != first,79,3.用循环链表求解约瑟夫问题,约瑟夫问题的提法:n 个人围成一个圆圈,首先第 1 个人从 1 开始,一个人一个人顺时针报数, 报到第 m 个人,令其出列。然后再从下一 个人开始,从 1 顺时针报数,报到第 m 个人,再令其出列,如此下去, 直到圆圈中只剩一个人为止。此人即为优胜者。 用不带表头结点的循环链表来组织。,80,例如 n = 8 m = 3,81,n = 8
31、 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-lLink-rLink = p-rLink-lLink,双向链表通常采用带表头
32、结点的循环链表形式。,非空表,空表,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 *right = NULL ) data = value; lLink = left
33、; 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) first = ptr; DblNode *Search (const T
34、/在链表中按后继方向寻找等于给定值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 = first-lLink = first; ;,90,te
35、mplate 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 ) /在链表中定位序号为i(0)的结点, d=0按前驱方 /向,d0按后继方向 if (first-rlink = first | i=0 ) return fir
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年承包经营合同
- 螺旋输送机维修操作指南
- 2025年资阳市雁江区区属国有企业招聘真题
- 2025年中国铁路兰州局集团有限公司招聘高校毕业生考试真题
- 2025年南昌进贤县公安局招聘警务辅助人员考试真题
- 2025年大连城投城市服务集团有限公司选聘真题
- 广西2024年高中学业水平合格性考试地理试卷真题(含答案)
- 2026年巴彦淖尔市民政系统事业单位人员招聘考试备考试题及答案详解
- 植物设计师职业路
- 2026年百色市血液中心事业单位人员招聘考试备考试题及答案详解
- AI时代网络安全产业人才发展报告(2025年)-安恒信息
- 公司保密工作总结汇报
- 20以内连减过关作业口算题大全附答案
- 新闻编辑实践作业汇报
- 硬币清点管理办法
- 工业机器人专业介绍课件
- 独舞大赛活动方案
- 统编版八年级下册历史期末复习:材料题答题技巧+常考50题专项练习题(含答案解析)
- 电力拖动自动控制系统-运动控制系统(第5版)习题答案
- 第九讲:信息与大数据伦理问题-工程伦理
- 码头防汛培训
评论
0/150
提交评论