一、线性表的概念
1.线性表的类型定义
- 线性结构的特点
在数据元素的非空有限集中:
- 存在唯一的一个被成为“第一个”的数据元素;
- 存在唯一的一个被称作“最后一个”的数据元素;
- 除第一个之外,集合中的每个数据元素均只有一个前驱;
- 除最后一个之外,集合中每个元素均只有一个后继。
- 线性表的类型定义
线性表是最常用且最简单的一种数据结构,一个线性表是n个数据元素的有限序列。
在稍复杂的线性表中,一个数据元素可以由若干个数据项组成。常把数据元素成为记录,含有大量记录的线性表又称为文件。
2.线性表的顺序表示
一般来说,线性表的第i个数据元素 ai 的存储位置为
LOC(ai)=LOC(a1)+(i−1)×l
线性表的这种机内表示称作线性表的顺序存储结构或顺序映像,通常称这种存储结构的线性表为顺序表。特点是,为表中相邻的元素 ai 和 ai+1 赋以相邻的存储位置 LOC(ai) 和 LOC(ai+1) 。以元素在计算机内“物理位置相邻”来表示线性表中数据元素之间的逻辑关系。
- 时间复杂度分析
在长度为n的线性表中插入一个元素时所需移动元素次数的期望值为
Eis=1n+1∑i=1n+1(n−i+1)=n2
在长度为n的线性表中删除一个元素时所需移动元素次数的期望值为
Edl=1n∑i=1n(n−i)=n−12
由此可见,在顺序存储结构的线性表中插入或删除一个数据元素,平均约移动表中一半的元素。若表长为n,则算法ListInsert和ListDelete的事件复杂度为 O(n) 。
- 优缺点分析
优点:无须为表示表中元素之间的关系而增加额外的存储空间;可以快速地存取表中任意位置的元素。
缺点:插入和删除操作需要移动大量的元素;使用前须实现分配好存储空间,当线性表长度变化较大时,难以确定存储空间的容量。分配空间过大会造成存储空间的巨大浪费,分配的空间过小,难以适应问题的需要。
3.线性表的链式表示
- 线性链表
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(存储结构可以是连续的也可以是不连续的)。
结点包括两个域:其中存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称作指针或链。n个结点链结成一个链表,即为线性表 (a1,a2,…,an) 的链式存储结构。又由于此链表的每个节点中只包含一个指针域,故又称线性链表或单链表。
- 静态链表
有时,也可借用一维数组来描述线性链表,便于在不设指针类型的高级程序设计语言中使用链表结构,称为静态链表。
在这种链表中,数组的一个分量表示一个结点,同时用游标(指示器cur)代替指针指示结点在数组中的位置。数组的第零分量可看成头结点,其指针域指示链表的第一个结点。
这种存储结构仍需要预先分配一个较大的空间,但在作线性表的插入和删除操作时不需要移动元素,仅需要修改指针,故仍具有链式存储结构的主要优点。假设S为SLinkList型变量,则S[0].cur指示第一个结点在数组中的位置,若设i=S[0].cur,则S[i].data存储线性表的第一个数据元素,且S[i].cur指示第二个结点在数组中的位置。一般情况,若第i个分量表示链表的第k个结点,则S[i].cur指示第k+1个结点的位置。
i=S[i].cur的操作实为指针后移(类似于p=p->next)。
- 循环链表
循环链表的特点是表中最后一个结点的指针域指向头结点,形成一个环。则从表中任意结点出发均可找到表中其他结点。还可以有多重链的循环链表。
循环链表的操作和线性链表基本一致,差别仅在于算法中的循环条件不是p或p->next是否为空,而是它们是否等于头指针。
- 双向链表
在单链表中从某个结点出发只能顺指针往后寻找其他结点,若要查寻结点的直接前驱,则需要从表头指针出发。在单链表中,NextElem的可执行时间为 O(1) ,e而PriorElem的执行时间为 O(n) 。
在双向链表的结点中有两个指针域,其一指向直接后继,另一指向直接前驱。
在双向链表中,若d为指向表中某一结点的指针,则显然有
d−>next−>prior=d−>prior−>next=d
双向链表的一个重要优点是:线性表中的位置i可以用指示含有第i个元素的芥蒂娜的指针表示。采用双向链表的代价是每个结点要增加一个额外的指针域,并且实现某些操作的程序会长一些。
- 数组与指针的选择
对于线性表的数组实现和指针实现,究竟采用哪种方法更合适,一般与经常使用那些操作有关,也与线性表的长度有关。
- 数组的实现方式要求在编译阶段就要确定线性表的最大长度。若无法确定增长的极限,则应该选择指针实现方式。
- 某些操作的执行,在一种方式中所花的时间比另一种方式中所花的时间要长。如在指针操作中,执行插入和删除操作所需时间为常数;而在数组方式中,执行这些操作的时间与表的长度成正比。反之,在数组的方式中,执行定位和后继函数等所需事件为常数,而在指针方式中却与表的长度成正比。
- 在线性表的指针实现方式中,由于插入或删除操作会改变表示某元素位置的变量的值,当以后再引用该变量时,就可能发生错误。因此,要小心或限制指针变量的使用。
- 在线性表的数组实现方式中,由于在任意时刻,元素都有可能没有充满整个数组,因此会浪费空间。而在指针实现方式中,链表中结点的个数与线性表中元素的个数相同,但每个结点需要额外的空间作为指针域。
4.顺序存储结构与链式存储结构对比
- 存储分配方式
顺序存储结构用一组连续的存储单元依次存储线性表的数据元素。单链表采用链式存储结构存放线性表的数据元素。 - 时间性能
采用顺序存储结构时,查找操作时间复杂度为 O(1) ,插入和删除操作需要移动平均一半的数据元素,时间复杂度为 O(n) 。采用单链表存储结构时,查找操作时间复杂度为 O(n) ,插入和删除操作不需要大量移动元素,时间复杂度仅为 O(1) 。 - 空间性能
采用顺序存储结构时,需要预先分配存储空间,分配的空间过大会造成浪费,非配的过小不能满足问题的需要。采用单链表存储结构时,可根据需要临时分配,不需要估计问题的规模大小,只要内存够就可以分配,还可以用于一些特殊情况,如一元多项式的表示。
二、线性表的实现
1.线性表的顺序表示实现
详情请参见线性表的顺序表示实现
2.线性表的链式表示实现
详情请参见线性表的链式表示实现
三、线性表的应用
1.制作简易通讯录
详情请参见制作简易通讯录
2.学生成绩管理系统
详情请参见学生成绩管理系统