2.3.2 使用数组模拟链表

链表(数组模拟)

链表也可以使用数组来实现,操作和基础知识比指针简单
但是个人觉得就思路和操作的清晰,以及对链表的理解而言,还是用指针好

模拟链表介绍

我们可以利用两个数组,分别记录链表要的两个东西:数据和地址
我们使用一个数组data,来存储每个结点的数据
使用另外一个数组right,来存储序列中每一个数右边的数的位置

比如现在二者如下:
位置 1 2 3 4 5 06 07 08 09
data: 2 3 5 8 9 10 18 26 32
right: 2 3 4 5 6 7 8 9 0

right[9] = 0 ,就代表data第九位的的右边没有数据

这里说一下,众所周知数组的第一位下标是0,但是书里按1开始算了
本着以书为本的原则,就没有修改,况且对于做链表而言也没区别
就是习惯了0开始数,看着难受

再如right[1]的值是2,指的是1号元素的右边的元素是2号元素(存放在data[2]中)

下面尝试按大小顺序,把6这个数值加入进去,那么该怎么做呢?
对于data数组比较简单,我们只需要做添加数据这个操作
让我们把这个数据添加到10号位置
位置 1 2 3 4 5 06 07 08 09 10
data: 2 3 5 8 9 10 18 26 32 6

对于right数组,会复杂一点,毕竟要排序和改地址
我们通过观察data数组,我们的6需要添加到5和8之间,也就是3号元素和4号元素之间

5对应的号数是3,8则是4.原本的地址是3号->4号,现在我们要加入6
那么我们新的次序是3号->10号->4号,即:
1.把3号“右边一位”改成10号
2.把10号“右边一位”改成4号
3.4号“右边一位”不变

位置 1 2 3 4 5 06 07 08 09 10
data: 2 3 5 8 9 10 18 26 32 6
right: 2 3 10 5 6 7 08 09 0 4

代码实例:

# include <stdio.h>
int main(){
    int data[101],right[101];  //大小没有硬性要求,

    int i,n,t,len ; 

    //开始读入已有的数
    scanf("%d",&n) ; 

    for(i=1 ; i<=n ; i++){
        scanf("%d",&data[i]) ; 
    }

    len = n ; 

    //初始化数组

    for(i = 1 ; i<= n ,i++){
        if(i!=n)    right[i] = i+1;
        else        right[i] = 0 ;
    }

    //直接在数组data末尾增加一个数
    len++;
    scanf("%d",&data[len]);

    //从链表透开始遍历
    t = 1 ;
    while(t!=0){
        if(data[right[t]] > date[len]){
            //如果当前结点的下一结点的值大于待插入数,则把数插入
            right[len] = right[t];
            //新插入的数的下一结点的编号,等于当前结点的下一结点编号  

            right[t] = len ; 
            //当前结点的下一个结点编号,就是新插入的数的编号

            break ; //插入完成,我们跳出循环
        }

        t = right[t] ;
    }

    //输出链表中所有的数
    t = 1 ;
    while(t!=0){
        printf("%d",data[t]);
        r = tight[t] ; //根据right数组的设置,读取下一个数
    }
    
    getchar();
    getchar();

    return 0 ;
}

小结

模拟链表以两个对应的数组,代替了指针
两者各有优劣,但是指针用的应该更多,毕竟你数组大小存在着限制
可以把模拟链表作为简单/削弱版的链表
不过,使用模拟链表一样可以实现双向链表和循环链表,这里就先不提了

posted @ 2021-11-18 20:33  RetenQ  阅读(71)  评论(0编辑  收藏  举报