数据结构与算法(三)-线性表之静态链表

前言:前面介绍的线性表的顺序存储结构和链式存储结构中,都有对对象地引用或指向,也就是编程语言中有引用或者指针,那么在没有引用或指针的语言中,该怎么实现这个的数据结构呢?

一、简介

  定义:用数组代替指针或引用来描述单链表,即用数组描述的链表叫做静态链表,这种描述方法叫做游标实现法;

  上面的静态链表图有两个数组游标数据,其中数据数组存储数据,而游标数组存储同下标为数据的下一个数据的下标值,简单模拟一下静态链表遍历的过程:

  1. 先查看下标为999的游标数组值:1;
  2. 根据游标数组值1,查找下标为1的数据:A;
  3. 然后查看游标数组为1的值:2;
  4. 根据游标数组值为2查找对应的数据数组的值:C;
  5. 然后循环3->4,直至游标数组的值为0;

二、代码实现

  静态链表的创建:

  • 我们对数组的第一个和最后一个元素做特殊处理,他们的data不存放数据;
  • 我们通常把未使用的数组元素称为备用链表;
  • 数组的第一个元素,即下标为0的那个元素的cur就存放备用链表的第一个结点的下标;
  • 数组的最后一个元素,即下标为MAXSIZE-1的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点作用;

  静态链表创建代码实现:

 public class StaticChain<T> {

    //数据链
    private T[] datas;

    //游标链
    private int[] vernier;

    private Integer size;

    private Integer length = 1000;

    StaticChain() {
        datas = (T[])new Object[length];
        vernier = new int[length];
        //将游标链的末位(头结点)初始化为1(下一节点的位置)
        vernier[length-1]=1;
        //将游标链的首位(空闲位的位置)初始化为1
        vernier[0]=1;
        size = 0;
    }

}

  插入操作:

    1、获取游标链下标为0的值为空闲位置的下标,并将该值对应下标所在的值放在游标链下标为0的地方;

    2、在5的位置插入值F,并将下标为5的游标链的值修改为0;

    3、若插入值为末位则直接将对应下标为4的游标链的值改为5,否则循环查找要插入值的上一位,并对应下标为4的游标链的值改为5;

插入操作代码如下:

    //插入到第几个元素的后面
    public void add(Integer index,T t) throws Exception {
        if (index>size)
            throw new Exception("outof index");
        int insertIndex = vernier[0];
        if (index == size) {
            int freeIndex = vernier[insertIndex];
            //将空闲位置的下标放入游标链的首位
            vernier[0] = freeIndex;
            //将刚插入末位值对应下标的游标链的值置为0
            vernier[insertIndex] = 0;
            //将值插入对应的位置
            datas[insertIndex] = t;
            //获取第几个元素的游标链对应的值
            Integer preIndex = this.getIndex(index);
            //将上一个元素的游标链的值改为插入的值的下标
            vernier[preIndex] = insertIndex;
            size++;
        } else {
            //获取第index+1个元素的游标链对应的值
            Integer nextIndex = this.getIndex(index+1);
            //将插入位置下标对应的游标链的值改为下一个元素的位置
            vernier[insertIndex] = vernier[nextIndex];
            datas[insertIndex] = t;
            //将上一个元素的游标链的值改为插入的值的下标
            Integer preIndex = this.getIndex(index);
            vernier[preIndex] = insertIndex;
            size++;
            //重置游标链的首位为空闲值下标
            Integer endIndex = this.getIndex(size);
            vernier[0] = vernier[endIndex];
            vernier[endIndex] = 0;
        }
    }

    //查询几个元素的游标链对应的下标
    private Integer getIndex(Integer index) throws Exception {
        int k = length - 1;
        for (int i = 1; i <= index; i++)
            k = vernier[k];
        if (k==-1) {
            throw new Exception("outof index");
        }
        return k;
    }

add()

删除操作:

   1、查找到要删除的节点的下标,将其对应的游标链的值取出来放在上一个游标链的指;

   2、并将删除的结点对应的游标链的值改为当前空闲指的下标,将空闲值的下标改为当前删除节点的下标;

删除操作代码如下:

    //删除第index个元素
    public T remove(Integer index) throws Exception {
        T data = null;
        if (index == 1) {
            Integer delIndex = vernier[999];
            data = datas[delIndex];
            int nextIndex = vernier[delIndex];
            vernier[length-1] = nextIndex;
            vernier[delIndex] = vernier[0];
            vernier[0] = delIndex;
        } else {
            Integer delIndex = this.getIndex(index);
            data = datas[delIndex];
            int nextIndex = vernier[delIndex];
            Integer preIndex = this.getIndex(index - 1);
            vernier[preIndex] = nextIndex;
            vernier[delIndex] = vernier[0];
            vernier[0] = delIndex;
        }
        return data;
    }

三、总结

  优点:

  • 在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点;
  • 解决了在某些没有引用和指针的高级语言中无法创建线性表的链式存储结构;

  缺点:

  • 没有解决连续存储分配(数组)带来的表长难以确定的为题;
  • 失去了顺序存储结构随机存取的特性;

在这里就要说一下静态链表和动态链表的区别:

  • 静态链表是数组实现的,是顺序存储结构,在物理地址上是连续的,而且需要预先分配大小。而动态链表适用内存申请函数(malloc)动态申请内存的,所以每个节点的物理地址是不连续的,要通过指针来顺序访问;
  • 静态链表的大小是一开始就定好的,所以当数组放满后就无法再放入了。而动态链表则无需考虑这种情况,随时加随时用;

总结:静态链表其实是为了给没有指针或引用的编程语言设计的一种实现单链表功能的方法,这种思想还是需要了解一下的——取他山之石以攻玉!

本系列参考书籍:

  《写给大家看的算法书》

  《图灵程序设计丛书 算法 第4版》

原文地址:https://www.cnblogs.com/lfalex0831/p/9641284.html

时间: 2024-08-27 18:52:28

数据结构与算法(三)-线性表之静态链表的相关文章

C++数据结构与算法_2_线性表 --顺序表的应用示例

h2.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }h2.cjk { font-family: "微软雅黑"; font-size: 16pt; }h2.ctl { font-family: "AR PL UMing CN"; font-size: 16pt; }h1 { margin-bottom: 0.21cm; }h1.western { fon

C++数据结构与算法_1_线性表 --顺序表的实现与分析

顺序表的实现与分析 引 --线性表的抽象基类: template <typename T> class LinearList { public: LinearList(); ~LinearList(); virtual int Size() const = 0; //返回线性表所能够存储的最大长度 virtual int Length() const = 0; //当前线性表的长度 virtual int Search(T &x) const = 0; virtual int Loca

数据结构与算法之线性表

前言 上一篇<数据结构和算法之时间复杂度和空间复杂度>中介绍了时间复杂度的概念和常见的时间复杂度,并分别举例子进行了一一说明.这一篇主要介绍线性表. 线性表属于数据结构中逻辑结构中的线性结构.回忆一下,数据结构分为物理结构和逻辑结构,逻辑结构分为线性结构.几何结构.树形结构和图形结构四大结构.其中,线性表就属于线性结构.剩余的三大逻辑结构今后会一一介绍. 线性表 基本概念 线性表(List):由零个或多个数据元素组成的有限序列. 注意: 1.线性表是一个序列. 2.0个元素构成的线性表是空表.

数据结构之第二章线性表之静态链式存储

1--特点:用一维数组来描述线性表,用游标代替指针指示节点在数组中的相对位置.不设“指针”类型的高级语言中适用链表结构. 2--线性表的静态链式存储结构 ////  静态单链表.h//  单链表的静态存储//// 6 //  Copyright (c) 2014年 dashuai. All rights reserved.// #ifndef SLIST_H#define SLIST_H#include <stdio.h>#include <stdlib.h> #define MA

数据结构、算法、线性表总结

一.数据结构 1.概念 1.数据类型和抽象数据类型是不同的概念. 2.逻辑结构分为线性结构(一对一).树形结构(一对多).图形结构(多对多). 3.时间复杂度(T(n)=O(f(n)):空间复杂度(占用的内存空间). 4.算法 1.BF算法:时间复杂度最坏为O(n*m). 2.kmp算法:时间复杂度最坏为O(n+m). 二.线性表 1.概念 1.顺序表结点的存储地址计算公式:Loc(ai)=Loc(a1)+(i-1)*C. 2.操作主要是查找用顺序表,进行插入.删除操作的适合用链表. 3.存储密

数据结构与算法之----线性表

01线性表 1.线性表的判断方式就是元素有且只有一个直接前驱和直接后继,元素可以为空,此时叫做空表 2.抽象数据类型标准格式 ADT 抽象数据类型名 DATA 数据元素之间逻辑关系的定义 Operation 操作 endADT 3.操作伪代码 Operation InitList(*L): 初始化操作,建立一个空的线性表L ListEmpty(L): 判断线性表是否为空表,如果为空返回true,否则返回false ClearList(*L): 将线性表清空(实际情况不是删除元素,而是将内存中的元

数据结构、算法及线性表总结

思维导图 重要概念 数据:是能被输入进计算机中,并能被计算操作处理的对象的总称 数据元素:是数据结构中讨论的基本单位 数据类型:整型.浮点型.字符型等等变量所具有的不同的数据种类 存储结构:又称物理结构,是描述数据具体在内存中的存储结构,分为线性结构和非线性结构 逻辑结构:是描述数据之间的相互关系,分为线性结构(一对一).树形结构(一对多).图状结构/网状结构(多对多) 算法:时间复杂度表示算法执行时间与问题规模之间的关系,是对运算时间的一个大致估计:空间复杂度表示算法执行时占用的内存空间 线性

数据结构与算法-总结线性表顺序存储结构的优缺点

这一章节主要总结线性表顺序存储结构的优缺点. 在总结之前,我们来讨论一下线性表顺序存储结构的执行方法的时间复杂度: 存储.读取:O(1) 插入.删除:O(n) 优点: 1.无需为表中的逻辑关系增加额外的存储空间 2.可以快速存取表中对象 缺点: 1.插入和删除需要移动大量的对象 2.存储设备的碎片化 3.当线性表过大的时候,很难确定长度 版权声明:本文为博主原创文章,未经博主允许不得转载.

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

静态链表的定义: 节点由一个一维数组和一个指针域组成,数组用来存放数据元素,而指针域里面的指针(又称游标)用来指向下一个节点的数组下标.这样的链表称之为静态链表. 链表中的数组第一个和最后一个位置需要特殊处理,不存数据.第一个位置(即数组0下标)的节点的指针用来存放备用链表的第一个节点的数组下标.最后一个位置(即数组长度MaxSize-1下标)的节点的指针用来存放指向有数值的第一个数据元素的数组下标,类似于单链表的头结点. 静态链表的示例图: 下面举一个摘抄自<大话数据结构>的例子,来解释一下