3.3 静态链表
对于那种没有指针的语言,有人想出用数组代替指针描述单链表,我们把这种用数组描述的链表叫做静态链表。
3.3.1静态链表定义
首先我们让数组的元素都是由两个数据域组成,data和cur。也就是说数组的每个下标都对应一个data和一个cur。
- 数据域data:用来存放数据元素。
- cur:用来存放后继元素的下标,相当于next的作用。
代码如下:
/*线性表的静态链表存储结构*/
typedef struct{
ElemType data;
int cur; /*游标,为0时表示无指向*/
} Component,StaticLinkList[MAXSIZE];
我们对数组的第一个和最后一个元素作为特殊元素处理,不存数据。我们通常把未使用的数据元素称为备用链表。数组第一个元素,即下标为0的元素的cur存放备用链表的第一个结点的下标;而数组最后一个元素的cur则存放第一个有数值的元素的下标,相当于单链表头结点的作用,当整个链表为空时,则为0。
此时图示相当于链表初始化的数组状态,代码如下:
/*将一维数组space中各分量链成一个备用链表,space[0].cur为头指针*/
Status InitList(StaticLinkList space){
int i;
for (i=0; i<MAXSIZE-1; i++)
space[i].cur = i+1;
space[MAXSIZE-1].cur = 0; /*目前静态链表为空,最后一个元素的cur为0*/
return OK;
}
3.3.2 静态链表的插入操作
例如我们要把B插入到A和C之间。
我们首先直接看图解:
- 先将B放入下标为5的空闲位置
- 然后再把A元素的cur改成5,让他指向B
- 最后把B元素的cur改成2,让他指向C
这样就完成了B插入A和C之间的操作,虽然三个元素看上去不相邻,但是在逻辑顺序上三者是有着A-B-C的顺序的。
代码实现:
/*若备用链表空间非空,则返回分配的结点下标,否则返回0*/
int Malloc_SSL(StaticLinkList space){
/*用于返回第一个空闲的数组的下标*/
int i = space[0].cur; /*当前数组第一个元素的cur存的值*/
if (space[0].cur)
space[0].cur = space[i].cur; /*由于要拿出一个分量使用,把下一个分量用来做备用*/
return i;
}
Status ListInsert(StaticLinkList L, int i, ElemType e){
int j,k,l;
k = MAXSIZE-1; /*k是最后一个元素的下标*/
if (i<1 || i>ListLength(L)+1)
return ERROR;
j = Malloc_SSL(L); /*获取空闲分量的下标*/
if (j){
L[j].data = e; /*将数值赋值给此分量*/
for (l=1; l<=i-1; l++){ /*找到第i个元素之前的位置*/
k = L[k].cur;
}
L[j].cur = L[k].cur; /*将i元素之前的cur赋值给新元素的cur*/
L[k].cur = j; /*把新元素的下标赋值给第i个元素之前元素的cur*/
return OK;
}
return ERROR;
}
3.3.3 静态链表的删除
静态链表的删除思路和插入思路其实差不多,这边直接给出代码,只不过需要释放删除的结点,代码如下:
/*删除在L中第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;
}
j = L[k].cur; /*要删除元素的下标*/
L[k].cur = L[j].cur; /*将要删除元素的cur赋值给要删除元素的前一元素cur*/
}
/*将下标为k的空闲结点回收到备用链表*/
void Free_SSL(StaticLinkList space, int k){
space[k].cur = space[0].cur; /*把第一个元素的cur的值赋值给要删除元素的cur*/
space[0].cur = k; /*将要删除元素下标赋值给第一个元素的cur*/
/*即让这个删除掉的元素成为第一个空闲结点*/
}
3.3.4 测试
代码如下:
int main(){
StaticLinkList L;
Status i;
i=InitList(L);
printf("初始化L后:L.length=%d\n",ListLength(L));
i=ListInsert(L,1,'F');
i=ListInsert(L,1,'E');
i=ListInsert(L,1,'D');
i=ListInsert(L,1,'B');
i=ListInsert(L,1,'A');
printf("\n在L的表头依次插入FEDBA后:\nL.data=");
ListTraverse(L);
i=ListInsert(L,3,'C');
printf("\n在L的“B”与“D”之间插入“C”后:\nL.data=");
ListTraverse(L);
i=ListDelete(L,1);
printf("\n在L的删除“A”后:\nL.data=");
ListTraverse(L);
printf("\n");
system("pause");
return 0;
}
运行结果:
初始化L后:L.length=0
在L的表头依次插入FEDBA后:
L.data=A B D E F
在L的“B”与“D”之间插入“C”后:
L.data=A B C D E F
在L的删除“A”后:
L.data=B C D E F
请按任意键继续. . .