第二章:3.线性表---静态链表的表示和实现

前言:

  由于一些高级程序设计语言中,并没有 “指针” 类型,因此上一节中用指针来描述的单链表不能被实现,这时候我们就会使用另一种形式链表:静态链表。

目录:

1.线性表的链式表示和实现

  1.1线性链表

    单链表(指针型线性链表)

    静态链表

  1.2循环链表

  1.3双向链表

正文:

  线性表的静态单链表存储结构:

    #define MAXSIZE 100;    //链表的最大长度

    typedef   struct{

      ElemType  data;

      int     cur;

    }component, SLinkList[MAXSIZE];

    其中数组的一个分量表示一个结点。 同时用游标 (即指示器  cur)代替指针指示节点在数组中的相对位置。

    数组的第0分量看为头结点,。其指针域指示链表的第一个结点。

    如下图所示:此种存储结构需要预先分配一个较大的存储空间,但是在线性表的插入和删除时不需要移动元素,仅仅需要修改指针,故仍然具有与链式结构的主要优点。

    

    假设S 为SLinkList 类型的变量,则 S[0].cur 指示第一个结点在数组中的位置,S[S[0].cur].data 是第一个数据元素,S[S[0].cur].cur 指示第二个数据元素在数组中的位置。若第 i 个分量表示链表的第 k 个结点,那么S[i].cur 为第 k+1 个结点所在的位置。

    静态链表实现插入和删除操作的关键是:我们要知道整个已分配的区域中,哪些分量已经被使用,哪些分量未被使用。解决办法是将所有未被使用过以及被删除的分量用游标链成一个备用的链表,每当进行插入的时候便从备用链表上取得第一个结点作为待插入的新结点;反之,在删除的时候将从链表中删除下来的结点链接到备用链表上。

      

  代码实现:

    注:此处实现功能为:,//由终端输入集合元素,先建立表示集合 A 的静态链表S ,然后在输入集合B 的元素的同时查找 S 表。
            //若存在 元素相同的则从S 中删除该元素,否则将元素 插入到 S 链表中。

    其他 ListInsert ,ListDelete ,GetElem ......等操作,根据静态链表存储特点即可方便的实现。

#include<stdio.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//链表的最大长度
#define MAXSIZE 100

//Status是函数的类型,其值是函数结果状态码
typedef int Status;
typedef int ElemType;

//静态链表的存储结构
typedef struct{
    ElemType data;
    int cur;
}component, SLinkList[MAXSIZE];

//将数组空间初始化为链表
void InitSpace_SL(SLinkList &space){
    for(int i=0;i<(MAXSIZE-1);i++){
        space[i].cur=i+1;
    }
    //将最后一个元素的游标 指针指向0
    space[MAXSIZE-1].cur=0;

}

//从备用链表中获取结点,返回被分配的结点对应的数组下标,如果所有空间已被用完则返回0
int Malloc_SL(SLinkList &space){
    if(space[0].cur!=0){                    //即备用链非空
        int i=space[0].cur;                    //
        space[0].cur=space[i].cur;            //备用链头结点 指向 第二个结点(即删除第一个结点)
        return i;                            //返回备用链的第一个结点对应的数组下标
    }
    return 0;                                //如果备用链没有空间可用,那么返回0
}

//将下标为k 的结点 回收到备用链当中
void Free_SL(SLinkList &space,int k){
    //即向备用链第一个结点处插入,数组下标k对应的结点
    space[k].cur=space[0].cur;
    space[0].cur=k;
}

//由终端输入集合元素,先建立表示集合 A 的静态链表S ,然后在输入集合B 的元素的同时查找 S 表。
//若存在 元素相同的则从S 中删除该元素,否则将元素 插入到 S 链表中。

//测试数据 A 有4 个元素:1,2,3,4
//           B 有3 个元素:2,6,7  预期结果为:1,3,4,6,7
void diffrence(SLinkList &space,int &S){
    InitSpace_SL(space);
    S=Malloc_SL(space);                //s为头结点
    int r=S;                        //r指向最后一个结点
    int m,n;
    //输入A 和 B 集合的元素个数
    printf("%s","请输入A集合元素总数:");
    scanf("%d",&m);
    printf("%s","请输入B集合元素总数:");
    scanf("%d",&n);    
    //简历 集合 A 的链表 S
    for(int i=0;i<m;i++){
        //从终端输入数据
        int data;
        printf("%s","请输入A集合元素值:");
        scanf("%d",&data);
        int cur=Malloc_SL(space);                //从备用链表取结点,并返回下标
        space[cur].data=data;                    //给返回的新结点赋值
        space[r].cur=cur;                        //将新结点添加到 S 链的 末尾
        r=cur;                                    //r 继续指向最后一个结点
    }
    space[r].cur=0;

//return;
    //输入集合B并进行和S的比较    
    for(int j=0;j<n;j++){
        int data;
        printf("%s","请输入B集合元素值:");
        scanf("%d",&data);
        int f=S;                                 //f指向S 链 的头结点

int equalFlag=0;                         //设置结点相等标识符,默认不行等,如果存在相等改为1    
        while(space[f].cur){
            if(data==space[space[f].cur].data){    
                int t=space[f].cur;
                if(space[f].cur==r)                 //如果删除的是 尾界点, 那么将 r 指向新的尾结点。
                    r=f;
                space[f].cur=space[space[f].cur].cur;         //删除结点                
                Free_SL(space,t);                 //回收结点                            
                equalFlag=1;                     //改变标识符
                break;
            }
            f=space[f].cur;                         //指针后移    
        }
        if(equalFlag==0){
            int cur=Malloc_SL(space);                 
            space[cur].data=data;                
            space[cur].cur=0;
            space[r].cur=cur;                     
            r=cur;
        }                
    }
    
    
}//时间复杂度为O(mxn)

//打印链表的所有数据
void PrintAll(SLinkList &space,int &S){
    int r=space[S].cur;
    while(r){
        printf("下标为:[%d] ",r);
        printf("data为:%d ",space[r].data);
        printf("游标指针为:[%d]\n",space[r].cur);
        r=space[r].cur;
    }
}

void main(){
    SLinkList SL;
    int S;
    diffrence(SL,S);
    PrintAll(SL,S); 
}      

    

运行结果:

   

总结:

  静态链表的 “静” 指的是静态链表不像 单链表那样每添加一个元素的时候去开辟内存空间,而是预先开辟一大块空间为之所用。

  那么根据是否在添加新结点的时候去开辟新的内存空间,与静态链表 相对应的 单链表 也可称为 动态链表。

时间: 2024-10-06 01:54:34

第二章:3.线性表---静态链表的表示和实现的相关文章

《数据结构》第二章:线性表

第2章:线性表 2.1 线性表的定义和基本操作 线性表是具有相同数据类型的n个数据元素的有限序列.n为表长,当n=0时该线性表是一个空表.a1是唯一的『第一个』数据元素,又称表头元素.An是唯一的『最后一个』数据元素,又称表尾元素.除第一个元素外,每个元素有且仅有一个直接前驱.除最后一个元素外,每个元素有且仅有一个直接后驱.线性表的特点:1) 表中元素个数有限.2) 表中元素具有逻辑上的顺序性,在序列中个元素排序有其先后次序.3) 表中元素都是数据元素,每个元素都是单个元素.4) 表中的数据类型

数据结构学习小结2 (第二章:线性表)

一.小结(1)认为最重要的内容小结:1.链表和顺序表的操作的代码实现.(初始化.创建.取值.查找.删除.插入)2.线性表的应用:线性表的合并:有序表的合并3.一元多项式的和的代码实现. (2)其他杂七杂八的收获:1.更深理解了->的含义:->是指针的指向运算符,通常与结构体一起使用.[从小组成员上获得的收获]2.通过作业和视频学习了单链表的逆转的实现3.尾指针不为空,尾指针->next才为空4.看了老师“带你打代码”里面有序表合并的代码写法,让我更熟悉一些操作,譬如: 新建一个结点: (

数据结构-线性表-静态链表

对于线性链表,也可用一维数组来进行描述.这种描述方法便于在没有指针类型的高级程序设计语言中使用链表结构. 静态链表是利用数组来实现,只是改变了实现方式,实际上链式存储说的存储的方式,数组只是实现的方式,不能将静态链表看做是顺序存储. 数组的元素都是由两个数据域组成,data和cur.也就是说,数组的每一个下标都对应一个data和一个cur. 数据域data用来存放数据元素,也就是通常我们要处理的数据:而游标cur相当于单链表中的next指针, 存放该元素的后继在数组中的下标.我们把这种用数组描述

数据结构读书笔记----------第二章 线性表

2.1 线性表的定义 线性结构的特点是数据元素之间是一种线性关系,在一个线性表中,数据元素的类型是相同的,或者说线性表是由同一类型的数据元素构成的线性结构.综上所诉:线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列. 2.2 线性表的顺序存储以及运算实现 //线性顺序存储的定义 #define Maxsize 100 typedef int DataType; typedef struct { DataType data[Maxsize]; int last; //用来记录线性表中最

(源代码见大话数据结构)线性表—静态链表

#include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXSIZE 1000 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALS 0 typedef int ElemType; typedef int Status; typedef struct { ElemType data; int cur; } Component,Stati

[数据结构 - 第3章补充] 线性表之双向链表(C语言实现)

一.什么是循环链表? 双向链表(double linked list)是在单链表的每个结点中,再设置一个指向其前驱结点的指针域.所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱. 既然单链表也可以有循环链表,那么双向链表当然也可以是循环表. 线性表的双向链表存储结构如下: typedef int ElemType; typedef struct DulNode { ElemType data; //数据域 DulNode *prior; //指向前驱结点的指针 DulN

[考研系列之数据结构]线性表之链表

1.链表分类 通过线性表概述,我们知道了链表这样一种数据结构,它又分成三类,分别是 单向链表 循环链表 双向链表 单向链表 单向链表的指针域只有一个指向下一个节点的指针,需要注意几点: 1.头指针--指向第一个节点 2.最后一个结点的指针指向NULL 3.头结点--在链表的第一个结点之前附设一个结点,它的数据域为空 所以,我们看到:  单向链表为空的<=>链表有且只有一个头结点<=>头结点的指针指向NULL 循环链表 循环链表和单向链表最大的不同就是:最后一个结点的指针不再指向NU

C语言 严蔚敏数据结构 线性表之链表实现

博主最近在考成都大学皇家计算机科学与技术专业,复习专业课数据结构,正好学习到线性结构中的线性表用链表这种存储结构来实现. 首先,数据结构包括1.数据的操作2.逻辑结构3.存储结构(数据结构三要素. 直接上代码,现阶段代码实现功能有:链表初始化.遍历.增.删.返回链表长度,后续功能陆续发布.其中肯定有很多问题,希望各位码哥留言. Linklist* InitList(int i)//i为链表大小 { Linklist *head; head = (Linklist*)malloc(sizeof(L

3、蛤蟆的数据结构笔记之三线性表单项链表实现

今天励志短语:"人生的价值,即以其人对于当代所做的工作为尺度." 昨天我们看了线性表的一些定义概念,今天来看下其中的单项链表代码如何实现. 1.  声明结构 如下声明一个指向结构的指针.(存放整数的节点,我们也可以根据需要创建字符的链表) typedef struct list_node *list_pointer; typedef struct list_node{ intdata; list_pointerlink; }; list_pointerptr = NULL; 2.  定