基于《大话数据结构》的学习笔记
用数组描述的链表叫静态链表
1.数组每个元素都是由两个数据域组成,data和cur。其中,数据data用于存放数据,游标cur相当于单链表的next指针,存放后继元素的下标。
2.第一个和最后一个元素不存数据。把未使用的数组元素成为备用链表。
3.最后一个有值元素的cur为0;第一个元素的cur存放备用链表的第一个结点的下标,整个链表为空则为0;数组最后一个元素的cur存放第一个有数值元素的下标,相当于单链表的头结点。
#define MAXSIZE 1000
typedef struct
{
int data;
int cur;
} Component, StaticLinkList[MAXSIZE];
Status InitList(StaticLinkList space)
{
int i;
for (i=0; i<MAXSIZE-1; i++)
space[i].cur = i+1;
space[MAXSIZE-1].cur = 0;
return OK;
}
静态链表的插入与删除
重写 malloc
int Malloc_SLL ( StaticLinkList space)
{
int i = space[0].cur; // 返回备用链表的第一个结点位置
if ( space[0].cur) // 如果满的返回0;因为最后一个有值元素的游标是0
space[0].cur = space[i].cur;// 初始化后这里返回的是i的下一个元素的游标
return i;
}
i 个元素前插入数据 e
Status ListInsert (StaticLinkList L, int i, int e)
{
int j, k, l;
k = MAXSIZE - 1;
if ( i < 1 || i > ListLenth(L) + 1)
return ERROR;
j = Malloc_SLL(L); // 获取备用链表初始位置下标
if (j) {
L[j].data = e;
for ( l = 1; l <= i-1; l ++ )
k = L[k].cur; // 找到地 i 个元素之前的位置
L[j].cur = L[k].cur; // 插入
L[k].cur = j; // j 是新元素
return OK;
}
return ERROR;
}
重写free
void Free_SSL ( StaticLinkList space, int k)
{
space[k].cur = space[0].cur; // k 链接备用链表
space[0].cur = k; // 将第一个元素链接 k
}
删除第 i 个元素
Status ListDelete ( StaticLinkList L, int i)
{
int j, k;
if ( i < 1 || i > ListLength(L))
return ERROR;
k = MAXSIZE - 1;
for ( j = 1; j <= i-1; j ++)
k = L[k].cur; // 此时 k 为 i-1 个元素
j = L[k].cur; // j 就是 第 i 个元素
L[k].cur = L[j].cur; // k 直接链接第 i+1 个元素
Free_SSL(L, j);
return OK;
}
优缺点分析(类似顺序表与单链表)
- 优点: 在插入删除时不需要移动元素
- 缺点: 表长难以确定, 搜索相对困难
循环链表:最后一个元素指向头指针,设置尾指针表示循环链表;
双向链表:在单链表的每个结点中,在设置一个指向其前驱结点的指针;