1.简介
大家通过前几章的学习,明白了什么是单链表,相比于顺序存储,在插入和删除方面,它的性能更加优越,但是小伙子们,有没有想过在C语言和Java出现之前,只有Basic等早期语言,而这些语言没有类似指针和地址的概念,那咱们编程界的六道仙人是如何来描述链表的尼?
对于没有指针的编程语言,可以用数组替代指针,来描述链表。让数组的每个元素由data和cur两部分组成,其中cur相当于链表的next指针,这种用数组描述的链表叫做静态链表。这种描述方法叫做游标实现法 ,存储方式如下图所示
当然,还有几点规则
-
我们对数组的第一个和最后一个元素做特殊处理,从数据来说:这两个位置不存放数据。
(注:如上图下标0或者下标999,这两个位置数据为空) -
这两个位置,从游标来说,第一个(下标0)元素的游标为该数组第一个没有存放数据元素的下标。并通常将未使用的数组元素称为备用链表。也就是说,存放的是备用链表中的第一个元素下标
(注:如该数组第一个没有存放数据的元素的下标是5,所以第一个元素的游标是第一个没有存放数据元素的下标,也就是说,下标0元素的游标也是5) -
最后一个元素的游标为该数组第一个有数值的元素的下标,相当于头结点
(注:第一个存储元素的下标为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.最后
同学们,学会了吗
代码在这里