静态链表-C语言实现

1.静态链表是在没有指针的编程语言里对链表的一种实现
2.主要是用数组模拟指针
3.在这里,使用结构体使数组的每一个空间可以存储一个数据元素(date)和一个游标(cur),游标的作用相当于链表的指针域,用于记录下一元素的下标是多少
4.在没有结构体(typedef)的语言中,也可以使用两个并行数组实现此功能

此种结构在编程中不一定能用得到,但是这种思想非常巧妙,非常值得我们学习,不多说,直接上代码,亲测可行,有详细注释

#include<stdio.h>

#define MAXSIZE 1000                //静态链表最大空间容量
typedef int ElemType;                //数据类型
typedef int Status;                    //返回值类型
#define OK 1                        //操作成功返回值
#define ERROR 0                        //操作失败返回值

typedef struct                        //静态链表的结构体
{
    ElemType date;                    //结点数据
    int cur;                        //结点游标(相当于链表中的地址)
}StaticLinkList[MAXSIZE];            //表名

/*
静态链表的初始化
第一个位置space[0]的cur指向第一个没有数据的位置空间
最后一个位置space[MAXSIZE-1]的cur指向第一个有数据的位置空间,即头结点
*/
Status InitList(StaticLinkList space)
{
    for(int i = 0; i < MAXSIZE-1; i++)            //为数组中的每个位置的游标赋值
        space[i].cur = i + 1;
    space[MAXSIZE-1].cur = 0;                    //使最后一个位置的游标为0
    return OK;                                    
}

/*
模拟链表中的malloc函数,在数组中寻找空闲位置空间作为新结点
*/
int malloc_SLL(StaticLinkList space)
{
    int i = space[0].cur;                        //将备用链表的第一个结点位置赋值给i
    if(space[0].cur)                            //如果space[0].cur不是0,即备用链表非空
        space[0].cur = space[i].cur;                //将备用链表的下一个空闲位置赋值给space[0]
    return i;
}

/*获得链表的长度*/
int ListLength(StaticLinkList L)
{
    int i, l;
    l = 0;                    //记录链表长度
    i = MAXSIZE - 1;        //获得头结点下标
    i = L[i].cur;            //获得头结点位置
    while(i)                //如果此下标 != 0
    {
        l++;                //长度加1
        i = L[i].cur;        //下标后移
    }
    return l;                //返回长度l
}

/*
静态链表的插入操作
*/
Status InsertLinkList(StaticLinkList L, int i, ElemType e)
{
    int j ,k, l;
    k = MAXSIZE-1;                            //获取头结点的下标
    if(i < 1 || i > ListLength(L)+1)        //判断要插入的位置是否合理
        return ERROR;
    j = malloc_SLL(L);                        //获得备用链表中的第一个位置下标
    if(j)                                    //如果此下标不是0,说明还有空间可用
    {
        L[j].date = e;                        //将此下标对应位置的数据域赋值为e
        for(l = 1; l < i; l++)                //遍历链表,寻找i位置之前的结点
            k = L[k].cur;                    //获得此结点的游标
        L[j].cur = L[k].cur;                //新结点的游标等于i-1位置的游标
        L[k].cur = j;                        //i-1位置的游标等于新结点的游标
        return OK;                            //操作成功
    }
    return ERROR;                            //操作失败
}

/*模拟free()函数,将删除的结点空间加入备用空间*/
void free_SSL(StaticLinkList space, int i)
{
    space[i].cur = space[0].cur;                    //删除位置的游标等于0位置的游标
    space[0].cur = i;                                //0位置的游标等于当前结点
}

/*静态链表的删除操作*/
Status DelLinkList(StaticLinkList L, int i)
{
    int j, k;
    if(i < 1 || i > ListLength(L)+1)                //判断删除的位置是否合理
        return ERROR;
    k = MAXSIZE - 1;                                //获得头结点的游标
    for(j = 1; j < i; j++)                            //寻找i位置
        k = L[k].cur;                                //游标后移
    j = L[k].cur;                                    //将要删除的位置下标赋值给j
    L[k].cur = L[j].cur;                            //使删除结点的前一结点的游标指向删除结点的游标
    free_SSL(L, j);                                    //释放删除的结点
    return OK;
}

/*静态链表的遍历操作*/
void PrintLinkList(StaticLinkList L)
{
    int i;
    int j = MAXSIZE - 1;                        //获得数组最后一个位置的下标
    j = L[j].cur;                                //获得此下标的游标值,即头结点的下标
//    printf("长度为%d
",ListLength(L));
    for(i = 1; i <= ListLength(L); i++)            //遍历此表
    {
        printf("第%d个结点的数据是:%d
", i, L[j].date);                //输出每个结点的数据
        j = L[j].cur;                            //获得下一结点的游标
    }
}


void main()
{
    StaticLinkList L;            //创建链表L
    int i, e;            //i为元素位置,e为元素内容

    while(true)
    {
        printf("请选择对静态链表的操作:
");
        printf("1.初始化
");
        printf("2.插入
");
        printf("3.删除
");
        printf("4.输出
");
        printf("5.退出
");
        int a;
        scanf("%d", &a);
        switch(a)
        {
            case 1:
                if(InitList(L))
                    printf("初始化成功
");
                else
                    printf("初始化失败
");
                break;
            case 2:
                printf("请输入需要插入的位置:");
                scanf("%d", &i);
                printf("请输入需要插入的元素:");
                scanf("%d", &e);
                if(InsertLinkList(L, i, e))
                    printf("插入成功
");
                else
                    printf("插入失败
");
                break;
            case 3:
                printf("请输入需要删除的位置:");
                scanf("%d", &i);
                if(DelLinkList(L, i))
                    printf("删除成功
");
                else
                    printf("删除失败
");
                break;
            case 4:
                PrintLinkList(L);
                break;
            case 5:
                return;
            default:
                printf("选择错误
");
                break;
        }
    }
}
原文地址:https://www.cnblogs.com/yurui/p/9508367.html