静态链表
用数组描述的链表叫静态链表,这种描述方法叫做游标实现法。
线性表的静态链表存储结构
#define MAXSIZE 1000
typedef struct
{
ElemType data; // 数据
int cur; // 游标
}Component, StaticLinkList[MAXSIZE];
对静态链表进行初始化相当于初始化数组
Status IninList(StaticLinkList spasce)
{
int i;
for(i=0; i < MAXSIZE-1; i++)
space[i].cur = i + 1;
space[maxsize-1].cur = 0;
return OK;
}
我们对数组的第一个和最后一个元素做特殊处理,他们的data不存放数据。
我们通常把未使用的数组元素称为备用链表
数组的第一个元素,即下标为0的那个元素的cur就存放备用链表的第一个结点的下标。
数组的最后一个元素,即下标为MAXSIZE-1的cur则存放第一个有数值的元素的下标,相当于单链表中的结点作用。
静态链表的插入操作
首先是获得空闲分量的下标:
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;
if(space[0].cur)
space[0].cur = space[i].cur;
// 把它的下一个分量用来作为备用
return i;
}
插入操作实现代码
/* 在L链表中的第i个位置插入e */
Status ListInstert(StaticLinkList L, int i, ElemType e)
{
int j, k, l;
k = MAX_SIZE - 1; // 数组的最后一个元素
if(i < 1 || i > ListLength(L) + 1)
{
return ERROR;
}
j = Malloc_SLL(L);
if(j)
{
L[j].data = e;
/* 找到要插入的元素的位置 */
for(l = 1; l <= i - 1; ;++)
{
k = L[k].cur;
}
L[j].cur = L[k].cur; // 将要插入元素前一个元素游标赋值给要插入元素的游标
L[k].cur = j; // 将要插入元素的下标赋值给要插入元素前一个元素的游标
return OK;
}
return ERROR;
}
静态链表的删除操作
将下标为k的空闲结点回收到备用链表
void Free_SLL(StaticLinkList space, int k)
{
space[k].cur = sapce[0].cur;
space[0].cur = k;
}
下面是实现代码
/* 删除L链表中的第i个位置元素 */
Status ListDelete(StaticLinkList L, int i)
{
int j, k;
if(i < 1 || i > ListLength(L))
{
return ERROR;
}
k = MAX_SIZE -1;
/* 找到要删除的元素的位置 */
for(j = 1; j <= i-1; j++)
{
k = L(k).cur;
}
j = L(k).cur; // 把删除元素的前一个元素的游标赋值给j
L[K].cur = L[j].cur; // 再把删除元素的游标赋值给前一个元素游标
Free_SLL(L, j);
return OK;
}
静态链表的数据元素的个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE-1].cur;
while(i)
{
i = L[i].cur;
j++; // j就是数据元素的个数
}
return j;
}
静态链表的优缺点
优点:
在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点。
缺点:
没有解决连续存储分配(数组)带来的表长难以确定的问题
失去了顺序存储结构随机存取的特性
快速找到未知长度单链表的中间结点
利用快慢指针原理:设置两个指针*search、 *mid都指向单链表的头结点。其中 *search的移动速度是 *mid的2倍。当 *search指向末尾结点的时候,mid正好就在中间了
Status GetMidNode(LinkList L, ElemType *e)
{
LinkList search, mid;
mid = search = L;
while(search->next != NULL)
{
/* search的移动速度是mid的2倍 */
if(search->next->next != NULL)
{
search = search->next->next;
mid = mid->next;
}
else
{
search = search->next;
}
}
*e = mid->data;
return OK;
}