(三)静态链表
 
    用一维数组实现线性链表---静态链表
    顺序存储结构也可以实现链表存储功能。首先开辟一个足够大的结构体数组。结构体的一个成员存放数据元素,另一个成员存放链表中下一个数据元素在数组中的位置(“游标”),这称为静态链表。
    静态链表存于数组中,但链表的输出却不是按数组的顺序输出的,而是由一个指定的位置开始根据游标依次输出的。
 
    1.静态链表类型定义
 
#define MAXSIZE 1000 // 链表的最大长度

typedef struct
{
    elemtype data;
    int cur
;    //指示域(代替指针),指示后继结点在数组中的位置;
                //数组的0分量可看作头结点,其指示域指示链表的第一个结点

} component, SLinkList[MAXSIZE];
     备用链表的概念:
为了管理存储结点的数组中哪些结点是已经插入到链表中的,哪些是没有插入到链表中,要在数组中定义两个链表,一个是有真实存储内容的链表,另一个是备用链表(空闲链表),数组中的所有结点都在这两个链表中,插入新结点时,从备用链表中删除一个结点插入到真实链表中,删除结点时,从真实链表中删除相应的结点插入到备用链表中。
    静态链表与单链表的主要区别:
    (1)单链表结点通过malloc函数产生,结点被限制在动态存储区这个大范围内。因此,指示结点位置的指针类型实际上是长整型。而静态链表的结点被限制静态数字这个小范围内。因此,指示结点位置的指针(类似指针)一般为整型,甚至可以是字节型(max_size小于256)。
    (2)单链表不用的结点用free函数释放,而静态链表中不用的结点要自己管理(插入到备用链表中)。
    一般把数组中下标为0的单元SLinkList[0]设为备用链表的头结点,把最后一个单元SLinkList[MAXSIZE-1]设为真实链表的头结点。
    2.静态链表的基本操作
/*申请新单元:若备用链表非空,从被备用链表中新分配出一个结点(备用链表的第一个结点),返回该结点在数组中的下标(位置),否则返回0*/
/*将下标为k的空闲结点回收到备用链表中(成为备用链表中的第一个结点)*/
 
/*构造一个空的链表L,表头为L的最后一个单元L[MAXSIZE-1],其余单元链成一个备用链表,表头为L的第一单元L[0],"0"表示“空指针”*/
 
/*将表L重置为空链表*/
 
/*若L是空表,返回TRUE,否则返回FALSE*/
 
/*返回L中的数据元素个数*/
 
/*用e返回L中的第i个元素的值*/
 
/*在静态链表中查找第一值为e的元素,返回它在表中的为序,没找到则返回0*/
 
/*若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,成功返回ok,否则error*/

/*若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,成功返回ok,否则error*/

/*在L中第i个元素之前插入新的数据元素e*/

/*删除在L中第i个元素,用e返回其值*/

/*依次对L中的每一个元素调用函数visit()*/
/*申请新单元:若备用链表非空,从被备用链表中新分配出一个结点(备用链表的第一个结点),返回该结点在数组中的下标(位置),否则返回0*/
int Malloc(SLinkList space)
{
    int i = space[0].cur;
//备用链表的第一个结点

    if(i)
//非空

        space[0].cur = space[i].cur;
//备用链表的头结点指向原第二个结点(现第一个结点)

    return i;
}

/*将下标为k的空闲结点回收到备用链表中(成为备用链表中的第一个结点)*/
void Free(SLinkList space ,int k)
{
    space[k].cur = space[0].cur;
    space[0].cur = k;
}

/*构造一个空的链表L,表头为L的最后一个单元L[MAXSIZE-1],其余单元链成一个备用链表,表头为L的第一单元L[0],"0"表示“空指针”*/
void InitList(SLinkList L)
{
    int i;
    L[MAXSIZE-1].cur = 0;
//空链表的表头

    for(i=0;i<MAXSIZE-2;i++)
//其余(除了链表表头和备用链表表头)maxsize-2个单元链成备用链表

        L[i].cur = i+1;
    L[MAXSIZE-2].cur = 0;
//备用链表的尾元素指向空

}

/*将表L重置为空链表*/
void ClearList(SLinkList L)
{
    int k,j,i;
    i = L[MAXSIZE-1].cur;
//i指向链表中的第一个结点

    L[MAXSIZE-1].cur = 0;
//置为空表

    k = L[0].cur;
//k指向备用链表的第一个结点

    L[0].cur = i;
//把链表的结点连接到备用链表的表头

    while(i)
//寻找链表尾,保存到j中

    {
        j = i;
        i = L[i].cur;
    }
    L[j].cur = k;
//备用链表的第一结点接到链表的尾部

}

/*若L是空表,返回TRUE,否则返回FALSE*/
Status ListEmpty(SLinkList L)
{
    if(L[MAXSIZE-1].cur == 0)
        return TRUE;
    else
        return FALSE;
}

/*返回L中的数据元素个数*/
int ListLength(SLinkList L)
{
    int j = 0;
    int i = L[MAXSIZE-1].cur;
    while(i)
    {
        j++;
        i = L[i].cur;
    }
    return j;
}

/*用e返回L中的第i个元素的值*/
Status GetElem1(SLinkList L,int i,elemtype *e)
//不调用ListLength()

{
    int k = L[MAXSIZE-1].cur;
    int j = 0;
    if(i<1)
        return ERROR;
    while(k)
    {
        if(++j == i)
        {
            *e = L[k].data;
            return OK;
        }
        k = L[k].cur;
    }
    return ERROR;
}

Status GetElem2(SLinkList L,int i,elemtype *e)
//调用ListLength()

{
    int m,k=MAXSIZE-1;
    if(i<1||i>ListLength(L))
        return ERROR;
    for(m=0;m<i;m++)
        k = L[k].cur;
    *e = L[k].data;
    return OK;
}

/*在静态链表中查找第一值为e的元素,返回它在表中的为序,没找到则返回0*/
int FindElem(SLinkList L,elemtype e)
{
    int i = L[MAXSIZE-1].cur;
    while(i && L[i].data != e)
        i = L[i].cur;
    return i;
}

/*若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,成功返回ok,否则error*/
Status PriorElem(SLinkList L,elemtype cur_e,elemtype * pre_e)
{
    int j,i=L[MAXSIZE-1].cur;
//i指向链表的第一个结点位置

    if(!i)
//若L为空

        return ERROR;
    do
    {
        j = i;
        i = L[i].cur;
//指向下一个元素

    }
    while(i && cur_e != L[i].data);
    if(i)
    {
        *pre_e = L[j].data;
        return OK;
    }
    return ERROR;
}

/*若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,成功返回ok,否则error*/
Status NextElemtype(SLinkList L,elemtype cur_e,elemtype * next_e)
{
    int j,i=FindElem(L,cur_e);
    if(i)
    {
        j=L[i].cur;
        if(j)
        {
            *next_e = L[j].data;
            return OK;
        }
    }
    return ERROR;
}

/*在L中第i个元素之前插入新的数据元素e*/
Status ListInsert(SLinkList L,int i,elemtype e)
{
    int m,j,k = MAXSIZE-1;
    if(i<1 || i>ListLength(L)+1)
        return ERROR;
    j = Malloc(L);
    if(j)
//申请成功

    {
        L[j].data = e;
        for(m=0;m<i-1;m++)
//将k移到第i-1个位置

            k = L[k].cur;
        L[j].cur = L[k].cur;
        L[k].cur = j;
        return OK;
    }
    return ERROR;
}

/*删除在L中第i个元素,用e返回其值*/
Status ListDelete(SLinkList L,int i,elemtype *e)
{
    int j,k=L[MAXSIZE-1].cur;
    if(i<1 || i>ListLength(L))
        return ERROR;
    for(j=0;j<i-1;j++)
//使k指向第i-1个元素

        k = L[k].cur;
    j = L[k].cur;
//待删除的位置

    L[k].cur = L[j].cur;
    *e = L[j].data;
    Free(L,j);
    return OK;
}

/*依次对L中的每一个元素调用函数visit()*/
void ListTraverse(SLinkList L,void(*visit)(elemtype))
{
    int i = L[MAXSIZE-1].cur;
    while(i)
    {
        visit(L[i].data);
        i = L[i].cur;
    }
}