其实C语言真是好东西,它具有的指针能力,使得它可以非常容易地操作内存中的地址和数据,这比其他高级语言更加灵活方便。后来的面向对象语言,如Java、C#等,虽不使用指针,但因为启用了对象引用机制,从某种角度也间接实现了指针的某些作用。但对于一些语言,如Basic、Fortran等早期的编程高级语言,由于没有指针,链表结构按照前面我们的讲法,它就没法实现了。怎么办呢?

    有人就想出来用数组来代替指针,来描述单链表。真是不得不佩服他们的智慧,我们来看看他是怎么做到的。

    首先我们让数组的元素都是由两个数据域组成,data和cur。也就是说,数组的每个下标都对应一个data和一个cur。数据域data,用来存放数据元素,也就是通常我们要处理的数据;而cur相当于单链表中的next指针,存放该元素的后继在数组中的下标,我们把cur叫做游标。

    我们把这种用数组描述的链表叫做静态链表,这种描述方法还有起名叫做游标实现法。

    为了我们方便插入数据,我们通常会把数组建立得大一些,以便有一些空闲空间可以便于插入时不至于溢出。

    1. /* 线性表的静态链表存储结构 */
    2. /* 假设链表的最大长度是1000 */
    3. #define MAXSIZE 1000
    4. typedef struct {
    5. ElemType data;
    6. /* 游标(Cursor),为0时表示无指向 */
    7. int cur;
    8. } Component,
    9. /* 对于不提供结构struct的程序设计语言,可以使用一对并行数组data和cur来处理。 */
    10. StaticLinkList[MAXSIZE];

    另外我们对数组第一个和最后一个元素作为特殊元素处理,不存数据。我们通常把未被使用的数组元素称为备用链表。而数组第一个元素,即下标为0的元素的cur就存放备用链表的第一个结点的下标;而数组的最后一个元素的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点作用,当整个链表为空时,则为0。如图3-12-1所示。
    image.png
    此时的图示相当于初始化的数组状态,见下面代码:

    1. /* 将一维数组space中各分量链成一备用链表, */
    2. /* space[0].cur为头指针,"0"表示空指针 */
    3. Status InitList(StaticLinkList space) {
    4. int i;
    5. for (i = 0; i < MAXSIZE - 1; i++)
    6. space[i].cur = i + 1;
    7. /* 目前静态链表为空,最后一个元素的cur为0 */
    8. space[MAXSIZE - 1].cur = 0;
    9. return OK;
    10. }

    假设我们已经将数据存入静态链表,比如分别存放着“甲”、“乙”、“丁”、“戊”、“己”、“庚”等数据,则它将处于如图3-12-2所示这种状态。
    image.png
    此时“甲”这里就存有下一元素“乙”的游标2,“乙”则存有下一元素“丁”的下标
    3。而“庚”是最后一个有值元素,所以它的cur设置为0。而最后一个元素的cur则因“甲”是第一有值元素而存有它的下标为1。而第一个元素则因空闲空间的第一个元素下标为7,所以它的cur存有7。