一、顺序表的定义
线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。
假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:
#define MaxSize 50 //定义线性表的最大长度
typedef struct{
ElemType data[MaxSize]; //顺序表的元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义
二、顺序表上基本操作的实现
1.插入操作
在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e。若i的输入不合法,则返回false,表示插入失败;否则,将顺序表的第i个元素及其后的所有元素右移一个位置,腾出一个空位置插入新元素e,顺序表长度增加1,插入成功,返回true。
bool ListInsert(SqList &L,int i,ElemType e){
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length>=MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--) //将第i个元素及之后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //在位置i处放入e
L.length++; //线性表长度加1
return true;
2.删除操作
删除顺序表L中第i(1<=i<=L.length)个位置的元素,若成功返回true,并将被删除的元素用引用变量e返回,否则返回false。
bool ListDelete(SqList &L,int i,Elemtype &e){
if(i<1||i>L,length) //判断i的范围是否有效
return false;
e=L.data[i-1]; //将被删除的元素赋值给e
for(int j=i;j<L.length;j++) //将第i个位置后的元素前移
L.data[j-1]=L.data[j];
L.length--; //线性表长度减1
return true;
}
3.按值查找(顺序查找)
在顺序表L中查找第一个元素值等于e的元素,并返回其位序。
int LocateElem(SqList L,ElemType e){
int i;
for(i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1; //下标为i的元素值等于e,返回其位序i+1
return 0; //退出循环,说明查找失败
}
一、链表的定义
线性表的链式存储又称单链表,它是通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。
data为数据域,存放数据元素;next为指针域,存放其后继结点的地址。
单链表结点结构:
单链表中结点类型的描述:
typedef struct LNode{ //定义单链表结点类型
ElemType data; //数据域
struct LNode *next; //指针域
}LNode, *LinkList;
利用单链表可以解决顺序表需要大量连续存储单元的缺点,但单链表附加指针域,也存在浪费存储空间的缺点。由于单链表的元素离散地分布在存储空间中,所以单链表是非随机存取的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。
二、单链表上基本操作的实现
1.采用头插法建立单链表
该方法是从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后。
头插法建立单链表
头插法建立单链表的算法如下:
LinkList List_HeadInsert(LinkList &L){ //逆向建立单链表
LNode *s; int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L—>next=NULL; //初始为空链表
scanf("%d",&x); //输入结点的值
while(x!=9999){ //输入9999表示结束
s=(LNode*)malloc(sizeof(LNode));//创建新结点
s->data=x;
s->next=L->next;
L->next=s; //将新结点插入表中,L为头指针
scanf("%d",&x);
}
return L;
}
采用头插法建立单链表时,读入数据的顺序与生成的链表中的元素的顺序是相反的。每个结点插入的时间为O(1),设单链表长为n,则总时间复杂度为O(n)。
2.采用尾插法建立单链表
头插法建立单链表的算法虽然简单,但生成的链表中结点的次序和输入数据的顺序不一致。希望两者次序一致,则可采用尾插法。该方法将新结点插入到当前链表的表尾,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。
尾插法建立单链表的算法:
3.按序号查找结点值
4.按值查找表结点
5.插入结点操作
6.删除结点操作
7.求表长操作
三、双链表
1、双链表的插入操作
在双链表中p所指的结点之后插入结点*s,其指针变化过程
s->next=p->next; //将结点s插入到结点p之后
p->next->prior=s;
s->prior=p;
p->next=s;
2.双链表的删除操作
删除双链表中结点p的后继结点q,其指针的变化过程:
删除操作的代码片段:
p->next=q->next; //图2.11中的步骤①
p->next->prior=p; //图2.11中的步骤②
free(q); //释放结点空间