《数据结构系列_线性表_链式存储之静态链表》

311 阅读4分钟

1.简介

大家通过前几章的学习,明白了什么是单链表,相比于顺序存储,在插入和删除方面,它的性能更加优越,但是小伙子们,有没有想过在C语言和Java出现之前,只有Basic等早期语言,而这些语言没有类似指针和地址的概念,那咱们编程界的六道仙人是如何来描述链表的尼?

对于没有指针的编程语言,可以用数组替代指针,来描述链表。让数组的每个元素由data和cur两部分组成,其中cur相当于链表的next指针,这种用数组描述的链表叫做静态链表。这种描述方法叫做游标实现法 ,存储方式如下图所示

当然,还有几点规则

  1. 我们对数组的第一个和最后一个元素做特殊处理,从数据来说:这两个位置不存放数据

(注:如上图下标0或者下标999,这两个位置数据为空)

  1. 这两个位置,从游标来说,第一个(下标0)元素的游标为该数组第一个没有存放数据元素的下标。并通常将未使用的数组元素称为备用链表。也就是说,存放的是备用链表中的第一个元素下标

(注:如该数组第一个没有存放数据的元素的下标是5,所以第一个元素的游标是第一个没有存放数据元素的下标,也就是说,下标0元素的游标也是5)

  1. 最后一个元素的游标为该数组第一个有数值的元素的下标,相当于头结点

(注:第一个存储元素的下标为1,那么最后一个元素的游标就是1)

  1. 其余元素的游标均为他下一个元素的下标

也就是这样

2.对应操作

2.1 初始化元素

/**

* 静态链表中的对象

* */

public class Node<T> {

    // 数据

    T data;

    // 游标

    int cur;

}

/**

* 静态链表

* */

public class StaticLinkedList<T> {

    // 封装的数组

    private Node<T>[] arr;

    /**

    * 初始化

    * */

    public StaticLinkedList(int length){

        arr = new Node[length];

        for(int i = 0; i < arr.length ;i++){

            arr[i] = new Node<>();

            // 非特殊点的元素游标为下一个元素的下标,

            // 第一个元素游标为除特殊点外,第一个没有数据的元素下标,现在链表为空,所以第一个元素的游标为1

            arr[i].cur = i + 1;

        }

        // 最后一个元素的游标为第一个存储数据元素的下标,但是现在链表为空,所以它的游标为0

        arr[arr.length - 1].cur = 0;

    }

}

完事之后就是这个熊样

2.1 插入元素

插入之前,先获取空位下标,也就是说,要将数据插到哪


/**

    * 获取空闲结点的下标

    * */

    public int getEmptyNodeIndex(){

        // 获取第一个元素的游标,也就是一个数组中,第一个空闲元素的下标。默认为0

        int i = arr[0].cur;

        if(i != 0){

            // 第一个元素的游标指向的是数组中第一个数据无值的元素下标,因为要将空闲位置插入元素,

            // 所以将第一个元素(下标为0)的游标指向要插入值的元素之后的空闲元素下标

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

        }

        return i;

    }

注:如上图所示,0号位置指向的是第一个空值的下标,也就是1号元素,所以先把1号元素取出,看看是不是最后一个元素,最后一个元素的游标为0,不是最后一个元素,就将它取出返回,因为要将数据插到这,所以0号元素的游标指向了2号元素,因为现在2号元素的是空值。

好,获取完空位坐标之后,就开始插入元素

(代码)


    /**

    * 插入数据

    * */

    public void addDataByIndex(int index, T value){

        // 判断插入的位置是否有效

        if(index < 0 || index > arr.length){

            throw new IllegalArgumentException("位置无效");

        }

        // 第一步:获取可插入的位置下标

        int emptyNodeIndex = getEmptyNodeIndex();

        // 将数据插入

        arr[emptyNodeIndex].data = value;

        // 更新最后一个元素的游标,它指向的是第一个有数据元素的下标

        int k = arr.length - 1;

        // 第二步:根据要插入的是第几个位置,安装个数,从最后一个元素的游标开始往前推导,找出该元素所在游标

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

            k = arr[k].cur;

        }

        // 更新刚插入数据的元素的游标为,他上一个元素的游标,也就是0,因为是从最后一个元素开始推的

        arr[emptyNodeIndex].cur = arr[k].cur;

        // 更新它上一个元素的游标为当前元素下标

        arr[k].cur = emptyNodeIndex;

    }

也就是这样

3.最后

同学们,学会了吗

代码在这里

这里最先更新