美文网首页
线性表(五) 静态链表

线性表(五) 静态链表

作者: 默默_David | 来源:发表于2018-11-01 14:27 被阅读26次

在没有指针的时代,要描述静态链表是比较困难的,前人想到了使用数组与游标来表示单链表的方法,如下图

静态链表

  在静态链表中,数组第一位的游标存放第一位没有数据的元素的下标,数组最后一位的游标存放第一位有数据的元素的下标。

  这种用数组描述的链表叫做静态链表,这种描述方法叫做游标实现法

1.  线性表的静态链表存储结构及初始化

#define MAXSIZE 1000

typedef struct {

    ElemType data;//数据

    int cur;//游标(Cursor)

}Component,StaticLinkList[MAXSIZE];

Status InitList(StaticLinkList space)

{

    for (int i = 0; i < MAXSIZE-1; i++) {

        space[i].cur = i+1;//初始化的时候除了最后一位,前面的游标都指向下一位

    }

    space[MAXSIZE-1].cur = 0;//最后一位游标指向第一位

    return OK;

}

  备忘:

    — 我们对数组的第一位和最后一位元素做特殊处理,他们的data不存放数据

    — 我们通常把未使用的数组元素称为备用链表

    — 数组的第一个元素,即下标为0的那个元素的cur就存放备用链表的第一个结点的下标

    — 数组的最后一个元素,即下标为MAXSIZE-1的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点作用

2.获取静态链表的长度

  ListLength

int ListLength(StaticLinkList L){

    int sum = 0;

    int i = L[MAXSIZE-1].cur;

    while (i) {

        sum++;

        i = L[i].cur;

    }

    return sum;

}

3.静态链表的插入操作

  静态链表中要实现元素的插入,需要解决的是:如何用静态模拟动态链表结构的存储空间分配,也就是需要的时候申请,不需要的时候释放

  在动态链表中,结点的申请和释放分别借用C语言的malloc()和free()两个函数来实现

  在静态链表中,操作的是数组,不存在像动态链表的结点申请和释放的问题,所以我们需要自己实现这两个函数,才可以做到插入和删除操作。

  另外,我们需要辨明数组中哪些分量未被使用,解决的方法是讲所有未被使用过的及已被删除的分量用游标链成一个备用的链表,每当进行插入时,便可以从备用链表上取得第一个节点作为待插入的新结点,如图所示,我们要在A后面插入B:

静态链表插入元素

  插入操作需要自己实现Malloc()函数,即获取备选链表的开始结点下标

  ListInsert:

  //获取空闲分量的下标

int Malloc_SLL(StaticLinkList space)

{

    int i = space[0].cur;

    if (i != 0) {

        //如果不是空链表,那么把备用链表的下一个分量作为备用链表的起始

        space[0].cur = space[i].cur;

    }

    return i;

}

Status ListInsert(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) {

        L[j].data = e;

        //循环找到第i-1个元素的下标

        for (l = 1; l < i; l++) {

            k = L[k].cur;

        }

        //将第i-1的游标值赋值给L[j].cur

        L[j].cur = L[k].cur;

        //让第i-1个元素指向L[j]

        L[k].cur = j;

        return OK;

    }

    return ERROR;

}

4.静态链表的删除操作操作

  删除如图示:

静态链表删除结点

  删除操作我们需要实现Free()函数,在调用Free()函数之前,将删除位置直接前驱结点的游标指向删除位置直接后继结点。

  ListDelete

//释放结点

void Free_SLL(StaticLinkList space,int k){

    //让此结点游标指向备用链表的开始结点

    space[k].cur = space[0].cur;

    //备用链表的头指针指向此结点

    space[0].cur = k;

}

Status ListDelete(StaticLinkList L,int i,ElemType *e)

{

    if (i < 1 || i > ListLength(L)) {

        return ERROR;

    }

    //返回数据

    *e = L[i].data;

    //初始化为头结点下标

    int k = MAXSIZE-1;

    int j;

    //循环找到i-1位置的下标

    for (j = 1; j < i-1; j++) {

        k = L[k].cur;

    }

    //临时变量存储i位置的下标

    j = L[k].cur;

    //将i-1位置的游标指向i+1位置的下标

    L[k].cur = L[j].cur;

    //释放i位置的结点

    Free_SLL(L, j);

    return OK;

}

5.静态链表优缺点总结

  .优点

  — 在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点

  .缺点

  — 没有解决连续存储分配(数组)带来的表长难以确定的问题

  — 失去了顺序存储结构随机存取的特性

  .总的来说,静态链表其实是为了给没有指针的编程语言设计的一种实现单链表功能的方法

  .尽管我们可以用单链表就不用静态链表了,但这样的思考方式是非常巧妙的,应该理解其思想,以备不时之需

相关文章

  • 数据结构与算法之数组与链表

    线性表包括数组,链表(单链表,双向链表,循环链表,双向循环链表,静态链表),栈(顺序栈,链式栈),队列(普通队列,...

  • 数据结构与算法之栈与队列

    线性表包括数组,链表(单链表,双向链表,循环链表,双向循环链表,静态链表),栈(顺序栈,链式栈),队列(普通队列,...

  • 数据结构之线性表(下)

    单链表:通过指针连接的线性表 没有指针的语言如果表示链表?答案是静态链表,静态链表用数组表示,使用元素的物理位序来...

  • 线性表(五) 静态链表

    在没有指针的时代,要描述静态链表是比较困难的,前人想到了使用数组与游标来表示单链表的方法,如下图 在静态链表中...

  • 数据结构——线性表

    线性表分为顺序存储结构和链式存储结构(单链表,静态链表,循环链表,双向链表)。 单链表(**一种动态结构,所占空间...

  • 四、线性表(五)、 静态链表

    数据结构目录 在没有指针的时代,要描述静态链表是比较困难的,前人想到了使用数组与游标来表示单链表的方法,如下图 在...

  • 线性表

    线性表是零个或者多个具有相同的数据元素的有限序列。 线性表的二大结构:顺序存储结构、链式存储结构(单链表、静态链表...

  • 数据结构之线性表

    线性表 #线性表#的存储结构包括: 顺序表 链表 链表的五种形式: 单链表 带头节点:head->next ==N...

  • 线性表

    1.线性表 1.1 顺序表(顺序存储) 静态分配 动态分配 1.2 单链表 单链表定义 不带头节点的单链表插入操作...

  • 线性表(静态链表)

    线性表:包含零个或多个数据元素的有限序列。 线性链表:指的是使用数组代替指针,来描述单链表;每个数据项含有data...

网友评论

      本文标题:线性表(五) 静态链表

      本文链接:https://www.haomeiwen.com/subject/ewhxxqtx.html