【前言】
关于静态链表的使用有两种方式,对于天勤书上采用0号单元作为头结点,-1表示空指针的方式。而严蔚敏版,将0号单元作为备用链表的头结点,0表示空指针。若需创建一个结点采用分配空间的方式获取结点地址。下面详细介绍严蔚敏版的静态链表:
【基本概念】
1.关于0号单元的使用:
1)直接将0号单元用作要创建的链表的头结点
2)将0号单元用作备用空间链表的头结点,要创建的链表的头结点从备用空间链表的备用单元中取出
【基本操作】
1.初始化
//将整个数组空间初始化为一个链表
void InitSpace_SL(SLinkList space)
{
int i;
for (i = 0; i < maxSize - 1; ++i)
{
space[i].cur = i + 1;
}
space[maxSize - 1].cur = 0;//0表示空指针
}
2.分配空间
int Malloc_SL(SLinkList space)
{
//若备用空间链表为非空则,返回分配结点下标(即结点地址),否则返回0
int i;
i = space[0].cur;//获取一个备用空间链表的结点
if (space[0].cur)//如果获取的该结点链表地址非空
space[0].cur = space[i].cur;//从备用链表中删除该结点,头结点的指针域指向下一个结点
return i;//返回备用结点地址
}
3.释放空间
void Free_SL(SLinkList space, int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
【相关知识】
【应用案例】
求(A-B)U(B-A)
【参考代码】
#include <stdio.h>
#include <stdlib.h>
#define maxSize 1000
typedef int ElemType;
typedef struct
{
ElemType data;
int cur;
}component, SLinkList[maxSize];
//1.将整个数组空间初始化为一个链表
void InitSpace_SL(SLinkList space)
{
int i;
for (i = 0; i < maxSize - 1; ++i)
{
space[i].cur = i + 1;
}
space[maxSize - 1].cur = 0;//0表示空指针
}
/*
题外话:void test(SLinkList space)中形参类型为component*,
而void test(SLinkList* space)形参类型为componet(*)[1000],
space是一个指向包含1000个元素的一维数组的指针变量
*/
//2.分配空间
int Malloc_SL(SLinkList space)
{
//若备用空间链表为非空则,返回分配结点下标(即结点地址),否则返回0
int i;
i = space[0].cur;//获取一个备用空间链表的结点
if (space[0].cur)//如果获取的该结点链表地址非空
space[0].cur = space[i].cur;//从备用链表中删除该结点,头结点的指针域指向下一个结点
return i;//返回备用结点地址
}
//3.释放空间。采用头插法,将下标为k的空闲结点链接到备用链表上
void Free_SL(SLinkList space, int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
//(A-B)U(B-A)
int difference(SLinkList space)
{
//先建立A的静态链表S,然后输入B元素(不用再建一个链表),输入的同时查找S对应元素
//若有相同的元素就删掉,没有则插入
int S;//定义A的头结点S
int r;//定义尾指针r
InitSpace_SL(space);
S = Malloc_SL(space);
r = S;
int m, n;//A和B元素的个数
printf("m n:");
scanf("%d%d", &m, &n);
//头插法建立S
int i, j;
printf("A:");
for (j = 0; j < m; ++j)
{
i = Malloc_SL(space);
scanf("%d", &space[i].data);
space[r].cur = i;//对比单链表:r->next = i;
r = i;
}
space[r].cur = 0;//r->next = NULL;
int b;
int k, p;
//依次输入B的元素,若在S中则删除,否则插入
printf("B:");
for (j = 0; j < n; ++j)
{
scanf("%d", &b);
p = S;
k = space[S].cur;//k = S->next
//在链表中查找值为k的元素下标,条件语句中严谨的写法为:k != space[r].cur
//这样写是为了保证能够一直在A中查找元素,防止将新插入的元素加入查找范围
while (k != space[r].cur && space[k].data != b)// k != r->next && k->data != b;
{//k从A中的第一个结点一直指向最后一个结点,与b比较完成后,k指向B中第一个结点,此时退出循环
p = k;//p指向k的前一个结点,用来做删除操作
k = space[k].cur;
}
//如果链表A中不存在该元素,则将r视作头结点,采用头插法插入b
if (k == space[r].cur)
{//r为A中的最后一个结点
i = Malloc_SL(space);
space[i].data = b;
space[i].cur = space[r].cur;
space[r].cur = i;
}
else
{
//删除k结点
space[p].cur = space[k].cur;
Free_SL(space,k);
//小陷阱,如果刚好删除的是尾结点则需要特殊处理
if (r == k)
r = p;//将r指向原k结点的前一个结点
}
}
return S;
}
//打印头结点为S的链表
void Print_List(SLinkList space, int S)
{
int p;
p = space[S].cur;
printf("S:");
while (p != 0)
{
printf("%d ", space[p].data);
p = space[p].cur;
}
}
int main()
{
SLinkList space;
int S;
S = difference(space);
Print_List(space, S);
return 0;
}
【运行结果】