静态链表

         本篇是静态链表的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;
}

运行结果如下:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值