关于线性表的定义、操作和实现
扫描二维码
随时随地手机看文章
1、线性表的定义
---- 通常,定义线性表为n(n>=0)个数据元素(或称为表元)的有限序列。记为L=(a1,a2,...,an). 其中L是表名,ai是表中的结点,
是不可再分割的数据。n是表中表元的个数,也称为表的长度,若n=0叫做空表。
---- 在非空的数据元素集合中,线性表的特点是:
--- 1)存在唯一的一个称作“第一个”的元素。
--- 2)存在唯一的一个称作“最后一个”的元素。
--- 3)除第一个元素外,集合中的每个元素均只有一个直接前驱。
--- 4)除最后一个元素外,集合中的每个元素均只有一个直接后继。
其中3)4)两个特点体现了线性表中元素之间的逻辑关系。
理解线性表的要点:
--- 表中元素具有逻辑上的顺序性,在序列中各元素排列有其先后次序。
--- 表中元素个数有限。
--- 表中元素都是数据元素。即每一个表元素都是不可再分的原子数据。
--- 表中元素的数据类型都相同。即每一个表元素占有相同数量的存储空间。
--- 表中元素具有抽象性。仅讨论表元素之间的逻辑关系,不考虑元素究竟表示什么内容。
2、线性表的操作
---- 线性表的主要操作有:
--- 1)表的初始化运算:将线性表置为空表。
--- 2)求表长度运算:统计线性表中表元素个数。
--- 3)查找运算:查找线性表中第i个表元素或查找表中具有给定关键字值的表元素。
--- 4)插入运算:将新表元素插入到线性表第i个位置上,或插入到具有给定关键字值的表元素的前面或后面。
--- 5)删除运算:删除线性表第i个表元素或具有给定关键字值的表元素。
--- 6)读取(访问)运算:读取线性表第i个表元素的值。
--- 7)复制运算:复制线性表所有表元素到另一个线性表中。
3、线性表的实现
3.1、线性表的顺序存储
------ 线性表的顺序存储又称为顺序表。它用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑关系相邻的两个
元素在物理位置上也相邻。因此顺序表的特点是表中各元素的逻辑顺序与其物理顺序相同。
------ 顺序表的静态存储分配
#define MaxSize 100 //显式的定义表的最大容量 typedef int ElemType; //定义表元素的数据类型 typedef struct { //顺序表的定义 ElemType data[MaxSize]; //静态分配存储表元素的数组 int n; //实际表元素个数,0<=n<=MaxSize }Sqlist;
在这种存储方式下,表元素ai存储在data[i-1]位置,存储结构如下图:
假设顺序表A的起始存储位置为Loc(1),第i个表项的存储位置为Loc(i),则有:Loc(i)=Loc(1)+(i-1) x sizeof(ElemType)
其中,Loc(1)是第一个表项的存储位置,即数组中第0个元素位置。sizeof(ElemType)是表中每个元素所占空间的大小。根据这个计算
关系,可随机存取表中的任一个元素。一维数组可以是静态分配的,也可以是动态分配的。
----- 在静态分配存储的情形下,由于数组的大小和空间事先已经固定分配,一旦数据空间占满,再加入新的数据就将产生溢出,此时
存储空间不能扩充,就会导致程序停止工作。
----- 在动态分配存储的情形下,存储数组的空间是在程序执行过程中通过动态存储分配的语句分配的,一旦数据空间占满,可以另外
再分配一块更大的存储空间,用以代换原来的存储空间,从而达到扩充存储数组空间的目的,同时需将表示数组大小的常量maxSize
放在顺序表的结构内定义,可以动态地记录扩充后数组空间的大小,提高结构的灵活性。
------ 顺序表的动态存储分配
#define InitSize 100 //表长度的初始定义 typedef int ElemType; //定义表元素的数据类型 typedef struct { //顺序表的定义 ElemType *data; //指示动态分配数组的指针 int maxSize,n; //数据的最大容量和当前表元素的个数 }Seqlist; //初始的动态分配语句为 data = (ElemType *)malloc(sizeof(ElemType)*InitSize); //C++ data=new ElemType[InitSize]; maxSize = InitSize;n=0;
3.2、线性表的链式存储
------ 线性表的链式存储又称为线性链表。在这种结构中数据元素存储在结点中,结点之间在空间上可以连续,也可以不连续,通过
结点内附的链接指针来表示元素之间的逻辑关系。因此在线性链表中逻辑上相邻的表元素在物理上不一定相邻。
以前在顺序结构中,每个数据元素只需要存数据元素信息就可以了,现在链式结构中,除了要存数据元素信息外,还要存储它的后继
元素的存储地址。因此,为了表示每个数据元素ai与其直接后继数据元素a(i+1)之间的逻辑关系,对数据元素ai来说,除了存储其本身
的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储地址/位置)。
------ 存储数据元素信息的域称为数据域,存储直接后继位置的域称为指针域。指针域中存储的信息称做指针或链。这两部分信息组成
数据元素ai的存储映像,称为结点(Node)。n个结点链接成一个链表,即为线性表的链式存储结构。
最简单的线性链表是单链表(链表的每个结点中只包含一个指针域),用C语言描述如下:
typedef int ElemType; //定义表元素的数据类型 typedef struct node { ElemType data; struct node *next; }Node,*LinkList;
此时,使用一个指向链表结点的指针head标识链表的表头:
Node *head;LinkList head;
为了表示链表收尾,链表最后一个结点的链接指针应置为空。
4、其他线性链表的形式
---- 根据结点中指针信息的实现方式,还有其他几种链表结构:
--- 1)双向链表:每个结点包含两个指针,指明直接前驱和直接后继元素,可在两个方向上遍历其后及其前的元素。
--- 2)循环链表:表尾结点的后继指针指向表中的第一个结点,可在任何位置上遍历整个链表。
--- 3)静态链表:借助数组来描述线性表的链式存储结构。(两个数据域,一个存放数据元素,一个存储该元素的后继在数组中的下标)
在链式存储结构中,只需要一个指针(头指针)指向第一个结点,就可以顺序访问到表中的任意一个元素。为了简化对链表状态的判定
和处理,特别引入一个不存储数据元素的结点,称为头结点,将其作为链表的第一个结点并令头指针指向该结点。
头结点的数据域可以不存储任何信息,也可以存储如线性表长度等类的附加信息,头结点的指针域存储指向第一个结点的指针(即第一个
元素结点的存储位置)。此时,单链表的头指针指向头结点。如下图所示: