线性结构的特点:
- 存在唯一的一个被称做“第一个”的数据元素,又称表头元素
- 存在唯一的一个被称做“最后一个”的数据元素,又称表尾元素
- 除第一个之外,集合中的每个元素均只有一个直接前驱
除最后一个之外,集合中每个数据元素均只有一个直接后继
1.线性表的类型定义
线性表(linear_list)是具有相同类型的 n 个数据元素的有限序列; 在稍复杂的线性表中, 一个数据元素可以由若干个数据项(item)组成. 在这种情况下,常把数据元素称为记录(record), 含有大量记录的线性表又称文件(file)
2. 线性表的顺序表示和实现
顺序表上基本操作的实现
顺序表的定义
线性表的顺序表示指的是一组地址连续的存储单元依次存储线性表的数据元素
第一个数据元素a1的存储位置,通常称做线性表的起始位置或基地址;线性表的这种机内表示称做线性表的顺序存储结构或顺序映像(sequential mapping),通常,称这种存储结构的线性表为顺序表
一维数组可以是静态分配的,也可以是动态分配的,用c语言动态分配的一维数组:
//--------线性表的动态分配顺序存储结构---------
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct{
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
动态分配,
Status InintList_Sq(){
// 构造一个空的线性表L
L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!L.elem)exit(OVERFLOW); //存储分配失败
L.length = 0; //空表长度为0
L.listsize = LIST_INIT_SIZE;//初始存储容量
return OK;
}//InintList_Sq
顺序表最主要的特点是随机访问,即通过首地址和元素序号可以在O(1)的时间内找到指定的元素
插入操作
平均时间复杂度为O(n)
删除操作
平均时间复杂度为O(n)
按值查找
平均时间复杂度为O(n)
插平均时间复杂度为O(n)入和删除操作:
3.线性表的链式表示和实现
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。数据元素的存储映像,称为结点(node),它包括两个域:
- 数据域:存储数据元素信息的域
- 指针域:存储直接后继存储位置的域
指针域中存储的信息称为指针或者链,n 个结点链结成一个链表,即为线性表的链式存储结构。又由于此链表的每个结点中只包含一个指针域,故又称线性链表或单链表。
指针为数据元素之间的逻辑关系的映像,则逻辑上相邻的两个数据元素其存储的物理位置不要求紧邻,由此,这种存储结构为非顺序映像或链式映像。
为了操作上的方便,在单链表第一个结点之前附加一个结点,称为头结点
头指针和头结点的区分:不管带不带头结点,头指针始终指向链表的第一个结点,而头结点是带头结点链表中的第一个结点,结点内通常不存储信息
单链表上基本操作和实现
单链表的定义
单链表是非随机存取的存储结构
按序号查找结点值/表结点
时间复杂度为O(n)
插入操作
s->next = p->next;
p->next = s;
删除操作
p->next = p->next->next;
p = GetElem(L,i-1);
q = p->next;
p->next = q->next;
free(q);
循环链表
循环链表(circular linked list)是另一种形式的链式存储结构,它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环
循环链表的操作和线性链表基本一致,差别仅在于算法中的循环条件不是p或p->next是否为空,而是它们是否等于头指针。
下图是两个循环链表合并:
这个操作仅需改变两个指针值即可,运算时间为O(1)
双向链表
双向链表(double linked list)的结点中有两个指针域,其一指向直接后继,另一指向直接前驱。
双链表中结点类型的描述:
typedef struct DNode{
ElemType adta;
struct DNode *prior,*next;
}DNode, *DLinklist;
双链表的插入操作
在双链表中p所指的结点之后插入结点*s:
- s->next = p->next;
- p->next->prior = s;
- s->prior = p;
- p->next = s;
双链表的删除操作
p->next = q->next;
q->next->perior = p;
free(q);
静态链表
我们也可以用一维数组来描述线性链表,称为静态链表。静态链表是借助数组来描述线性表的链式存储结构,结点也有数据域data和指针域next,这里的指针是结点的相对地址(数组下标),又称游标。和顺序表一样,静态链表也要预先分配一块连续的内存空间。
下图表示了插入数据“SHI”和删除数据“ZHENG”之后的状态: