zoukankan      html  css  js  c++  java
  • 静态链表-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;
            }
        }
    }
  • 相关阅读:
    androidstudio配置模拟器路径
    Linux常见命令
    逆向助手使用
    Git服务器回滚到固定版本
    Git使用
    使用本地Gradle版本
    系统模拟器创建
    AndroidStudio设置代理
    关联、参数化、思考时间、检查点、事务的设置方式
    SQL:内连接、左外连接、右外连接、全连接、交叉连接区别
  • 原文地址:https://www.cnblogs.com/yurui/p/9508367.html
Copyright © 2011-2022 走看看