补充:静态链表

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之间。

我们首先直接看图解:
在这里插入图片描述

  1. 先将B放入下标为5的空闲位置
  2. 然后再把A元素的cur改成5,让他指向B
  3. 最后把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
请按任意键继续. . .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

压力小子呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值