• 静态链表


             本篇是静态链表的C语言实现,实现书中算法2.13-2.17。

           将数组中的一个分量表示结点,同一时候用游标取代指针指示结点在数组中的相对位置的,用数组来描写叙述的链表叫做静态链表。

           对于静态链表我们应注意:数组的第一个和最后一个元素做特殊处理,他们的data域不存放数据;通常把未使用的数组元素及删除的数组元素称为备用链表;数组的第一个元素,下标为0的那个元素的cur存放的就是备用链表的第一个节点的下标数组的最后一个元素,下表为MAXSIZE-1的cur存放第一个有数值元素的下标,相当于单链表的头几点的作用;当前数组中的最后一元素(不一定为MAXSIZE-1)的游标为0.

                 主要实现例2-3——集合运算(A-B)U(B-A)来讨论静态链表的算法

    declaration.h

    #ifndef DECLARATION_H_INCLUDED
    #define DECLARATION_H_INCLUDED
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    #define INFEASIBLE -1
    #define OVERFLOW -2
    #define MAXSIZE 100
    #define ElemType char
    typedef int Status;
    typedef struct
    {
            ElemType data;
            int cur;//游标(指示器cur)取代指针指示结点在数组中的相对位置
    }component, SLinkList[MAXSIZE];
    //借用一维数组描写叙述线性链表,便于在不设“指针”类型的高级程序设计语言中使用链表结构
    #endif // DECLARATION_H_INCLUDED
    //数组的第0分量作头结点,其指针域指示链表的第一个结点。
    //这样的存储结构须要先分配一个较大的空间,但在作线性表的插入和删除时不需移动元素
    //仅需改动指针,故仍具有链式存储结构的主要长处。
    //若S为SLinkList型变量,第i个分量表示连表的第K个结点,则S[i].cur指示第K+1个结点的位置
    //整型游标i取代指针q,i=S[i].cur的操作相当于运行p=p->next;

    function.h

    #ifndef FUNCTION_H_INCLUDED
    #define FUNCTION_H_INCLUDED
    Status LocateElem_SL(SLinkList S, ElemType e);
    //在静态链表中查找e,若存在返回他的位序否则返回0
    void InitSpace_SL(SLinkList space);
    //将一维数组*space中各分量链成一个备用链表,(*space)[0].cur为头指针
    Status Malloc_SL(SLinkList space);
    //若备用链表非空,则返回分配的节点下标否则返回0
    void Free_SL(SLinkList space, int k);
    //将K为下标的空暇结点回收到备用链表
    void Difference(SLinkList space, int S);
    //依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)U(B-A)
    //的静态链表,S为其头指针。如果备用空间足够大,(*space)[0].cur为其头指针
    void Print_SL(SLinkList space);
    
    
    #endif // FUNCTION_H_INCLUDED

    function.c

    #include <stdio.h>
    #include "declaration.h"
    Status LocateElem_SL(SLinkList S, ElemType e)
    {
            //在静态链表中查找e,若存在返回他的位序否则返回0
            Status i=S[0].cur;      //i指示表中第一个结点,S[0]是头结点
            while(S[i].data != e && i)
            {
                    i=S[i].cur;
            }
            return i;
    }//LocateElem_SL
    void InitSpace_SL(SLinkList space)
    {
            //将一维数组*space中各分量链成一个备用链表,(*space)[0].cur为头指针
            Status i;
            for(i=0; i<MAXSIZE; i++)
                    space[i].cur=i+1;
            space[MAXSIZE -1].cur=0;   //当前数组中最后元素的游标为0
    }//InitSpace_SL
    Status Malloc_SL(SLinkList  space)
    {
            //若备用链表非空,则返回分配的节点下标否则返回0
            Status i=space[0].cur;
            if( space[0].cur )
                    space[0].cur=space[i].cur;
            return i;//i为备用链表中的第一个结点的下标,初始为1(此时整个链表空间都是空间的)
    }
    void Free_SL(SLinkList  space, int k)
    {
            //空表中插入数据时会调用Malloc_SL函数,将space[0].cur指向备用链表的第一个结点
            //将K为下标的空暇结点回收到备用链表
            space[k].cur=space[0].cur;
            space[0].cur=k;
    }//Free_SL
    void Difference(SLinkList  space, int S)
    {
            //依次输入集合A和B的元素,在一维数组*space中建立表示集合(A-B)U(B-A)
            //的静态链表,S为其头指针。如果备用空间足够大,(*space)[0].cur为其头指针
            Status m,n,i,j,p;
            ElemType b;
            InitSpace_SL(space);    //初始化备用空间
            S=Malloc_SL(space);  //生成S的头结点,S=1
            Status r=S;     //r指向S的当前最后结点
            printf("please enter m,n as the size of A and B:");
            scanf("%d%d",&m, &n);
             getchar();//读取多余的换行符
            for(j=1; j<=m ;j++)
            {
                    i=Malloc_SL(space); //循环内第一次调用时返回2
                    scanf("%c", &(space[i].data));//从下标2的位置開始复制
                    space[r].cur=i;      r=i;    //插入到表尾
            }//for,此时下标0位置的游标被置为8
            space[r].cur=0;      //      将A链表尾结点的指针置为空,r=7
    
            for(j=1 ;j<=n;j++)
            {
                    //为方便理解,下面凝视都是针对第一次循环时情况的详细分析
                    //依次输入B的元素,若不在当前表中则插入,否则删除
                    scanf("%c",&b);
                    p=S;//p=1
                    int k=space[S].cur;//k指向集合A中的第一个结点,即下标为2的c
                    while( k != space[r].cur   &&  space[k].data != b)  //k != 0
                    {
                            p=k;  k=space[k].cur;    //p来记载被操作元素的前一个位置的下标
                    }
                    if( k == space[r].cur) //space[r].cur=0,即A链表中不存在读入的变量b。
                    {
                            i = Malloc_SL(space);//i=8;
                            space[i].data = b;//插入'a'
                            space[i].cur = space[r].cur;//space[8].cur=0;
                            space[r].cur=i;//space[7].cur=8
                    }
                    else
                    {
                            //该元素已在表中
                            space[p].cur = space[k].cur;
                            Free_SL(space, k);
                            if(r == k)  r = p;  //若删除的是r所指结点则须要改动尾指针
                    }//else
            }//for
            Print_SL(space);
    
    }//difference
    void Print_SL(SLinkList space)
    {
            Status i=2;
            //依据游标间的关系打印(A-B)U(B-A)的结果
           while( space[i].cur <11)
            {
                    printf("%c",space[i].data);
                    i=space[i].cur;
            }
    }
    

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "declaration.h"
    #include "function.h"
    int main()
    {
            SLinkList space;
            int S=0;
            Difference(space, S);
            return 0;
    }
    

    执行结果例如以下:


  • 相关阅读:
    python算法(1)抓交通肇事犯
    vue(24)网络请求模块axios使用
    vue(23)Vuex的5个核心概念
    vue(22)Vuex的安装与使用
    JMeter分布式压测配置(五)
    命令行执行Jmeter脚本(四)
    BeanShell(二)
    Jmeter之测试片段(八)
    服务器资源监控之Perfmon
    Jmeter之线程组(四)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4073016.html
Copyright © 2020-2023  润新知