静态链表
用数组描述的链表
图转自网络
存储结构
#define MAXSIZE 1000 //即该链表最大长度为1000
typedef struct
{
ElemType data; //数据部分
int cur; //游标,为0时表示无指向
}Componet,StaticLinkList[MAXSIZE];
初始化
Status InitList(StaticLinkList space)
{
int i;
for(i=0;i<MAXSIZE-1;i++); //将游标序号从1开始依次排列到末尾-1处
space[i].cur = i+1;
space[MAXSIZE-1].cur = 0; //将末尾游标置0,即当前链表为空
return ok;
}
插入(插入到第i个节点前)
//获取备用链表在数组中的位置
int Malloc_SLL(StatixLinkList space)
{
int i = space[0].cur; //当前数组第一个节点的cur存的值
if(space[0].cur) //第一个值不为0
space[0].cur = space[i].cur; //更新备用链表的位置,即改变第一个节点的游标值
return i;
}
//在L中第i个元素之前插入新的数据元素e
Status ListInsert(StaticLinkList L,int i,ElemType e)
{
int i,k,l;
k = MAXSIZE -1; //获得数组最后一个节点的位置
if(i<1 || i>ListLength(L)+1)
return error; //i小于1或者大于数组个数,则返回错误
j = Malloc_SLL(L); //获取备用节点在数组中的位置
if(j) //若该位置不为0
{
L(j).data = e; //备用节点数据部分赋值
for(l=1 ; l<=i-1 ; l++) //循环遍历前i-1个数据,找到第i-1个节点在数组中的位置
{
K = L(K).cur; //将该位置赋值给k
}
L(j).cur = L(k).cur; //把原本第i个节点在数组中的位置,现在给到新的节点的游标
L(k).cur = j; //第i-1个节点现在的游标值指向新节点在数组中的位置j
return ok;
}
return error;
}
删除(删除L中第i个元素e)
//将在数组中位置为k的空闲节点回收到备用链表
void Free_SSL(StaticLinkList space,int k)
{
space[k].cur = space[0].cur; //将当前备用地址赋给即将删除的节点的游标
space[0].cur = k; //更新备用节点地址设置为k
}
//删除第i个元素
Status ListDelete(StaticLinkList L,int i)
{
int j,k;
if(i<1||i>ListLength(L)) //i小于1或者超过最大长度
return error;
k = MAXSIZE-1; //最后节点
for(j = 1;j <= i-1;j++) //遍历找到第i-1个节点的位置赋给k
{
k = L[k].cur
}
j = L[k].cur; //获得第i个节点在数组中的位置
L[k].cur = L[j].cur //将原本第i+1个节点的位置给原本第i-1个节点的游标
Free_SSL(L,j); //释放位置为j的节点
return ok;
}
返回链表长度
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE-1].cur; //从尾节点处获得第一个数据节点的位置
while(i) //为0即到达最后一个数据节点
{
i = L[i].cur; //依次遍历到下一个节点
j++; //计数+1
}
return j;
}
优点:在插入和删除时只需要修改游标不需要移动数据
缺点:表长仍为固定值;失去了顺序存储结构的随机存取特性
用处:用于没有指针的高级语言设计的一种实现方法,不需要malloc和free函数
循环链表
将单链表中终端节点的指针端由空指针改为指向头结点,使整个单链表成为一个环,称为单循环链表,简称循环链表
区别(与单链表):单链表判断p->next是否为空,单循环链表判断p->next是否为头节点
优化:为了操作更加方便,可以增加一个尾指针指向最后一个节点,于是第一个数据节点即为rear->next->next
合并两个循环链表
p = rearA -> next; //记录A的头节点
rearA -> next = rearB -> next -> next; //将A的尾节点指向改成B的第一个数据节点
q = rearB -> next; //保存B的头节点
rearB -> next = p; //将B的尾节点指向A的头节点
free(q); //释放B的头节点
双向链表
在每个节点中存在两个指针域,分别指向前一个和后一个节点
//线性表双向链表存储结构
typedef struct DulNode
{
ElemType data;
struct DulNode *prior; //前驱指针
struct DulNode *next; //后继指针
}DulNode, *DuLinkList;
插入操作(s插入到p后)
思想:先修改需要插入节点的前后指针指向,再修改原链表中的节点的指针指向
s-> prior = p;
s -> next = p -> next;
p - next ->prior = s;
p ->next = s;
删除操作(删除s)
思想:将p的前后端节点的指针相互连接,然后释放p
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);