静态链表

1 实现原理和步骤

单向链表是通过引用next指向下一个节点来实现的,当对链表进行增删操作时,只需移动引用,而不需要移动数据,算法的时间复杂度为O(1)。
在这里插入图片描述
在这里插入图片描述
问题来了,如果Node1不通过引用next,有什么办法能够快速建立与Node2的连接?答案是通过数组下标。上述节点的数据结构变为:

在这里插入图片描述
即使用数据类型为Node的数组来放置链表的所有节点,每个节点中的cur数值存放链表下一个节点的物理下标,这种类型的链表称为静态链表。
在这里插入图片描述
其中,物理下标是节点存放在数组的真实下标,而逻辑下标指该节点在链表中的位置。

2 完整代码

package linkedlist;


import java.util.LinkedList;

/**
 * 静态链表
 */
public class StaticList<T> {
    /**
     * 默认大小
     */
    private final int DEFAUL_SIZE = 10;

    /**
     * 静态链表,底层是数组
     */
    private Node<T>[] list;

    /**
     * 空闲节点下标
     */

    private int currentFree;

    /**
     * 静态链表头节点的物理下标
     */
    private int head;

    /**
     * 静态链表长度
     */
    private int size;

    /**
     * 静态链表节点的数据结构
     * @param <T>
     */
    class Node<T> {
        T data;
        int cur;
    }

    /**
     * 初始化
     */
    public StaticList() {
        list = new Node[DEFAUL_SIZE];

        for (int i = 0; i < DEFAUL_SIZE; i++) {
            list[i] = new Node<T>();
            list[i].cur = i + 1;
        }

        list[DEFAUL_SIZE - 1].cur = -1;
        currentFree = 0;
        head = 0;
        size = 0;

    }


    /**
     * 获取第position个节点的物理下标
     *
     * @param position
     * @return
     */
    public int getIndex(int position) {
        if (position < 0 || position > size - 1) {
            throw new IndexOutOfBoundsException("查询索引越界");
        }

        int i = 0;
        int temp = head;

        while (i < position) {
            temp = list[temp].cur;
            i++;
        }

        if (i == position) {
            return temp;
        }

        return -1;

    }

    /**
     * 按逻辑位置顺序向静态链表中添加新元素
     *
     * @param data
     * @return
     */
    public boolean add(T data) {
        if (currentFree >= DEFAUL_SIZE) {
            throw new IndexOutOfBoundsException("链表已满,添加数据失败:" + data);
        }

        list[currentFree].data = data;
        currentFree =  list[currentFree].cur;
        size++;
        return true;
    }

    /**
     * 向静态链表指定逻辑位置插入新元素
     *
     * @param position
     * @param data
     * @return
     */
    public void add(int position, T data) {

        if (position < 0 || position >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        } else if (currentFree >= DEFAUL_SIZE) {
            throw new IndexOutOfBoundsException("链表已满,添加数据失败:" + data);
        }

        list[currentFree].data = data;
        int nextCurrentFree = list[currentFree].cur;    //空闲节点的后继节点

        if (position == 0) {   //插入位置在链表头结点
           list[getIndex(size - 1)].cur = list[currentFree].cur;
           list[currentFree].cur = head;
           head = currentFree; //更新链表头结点位置

        } else {
            int preIndex = getIndex(position - 1); //插入位置前一个节点的真实下标
            int nextIndex = list[preIndex].cur;    //插入位置后一个节点的真实下标
            int preCurrentFree = getIndex(size - 1); //空闲节点的上的前驱节点

            list[preIndex].cur = currentFree;
            list[currentFree].cur = nextIndex;
            list[preCurrentFree].cur = nextCurrentFree;
        }

        currentFree =  nextCurrentFree;
        size++;
    }

    /**
     * 获取静态链表制定逻辑位置的节点
     * position
     *
     * @param position
     * @return
     */
    public Node<T> get(int position) {
        int tIndex = getIndex(position);
        if (tIndex != -1) {
            return list[tIndex];
        }

        return null;
    }

    /**
     * 查询静态链表长度
     *
     * @return
     */
    public int size() {
        return size;

    }

    /**
     * 刪除链表指定逻辑位置元素
     *
     * @param position
     * @return 返回
     */
    public T delete(int position) {

        if (position < 0 || position >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }

        int index = getIndex(position); //待删节点的物理位置
        int preIndex = -1;  //待删节点的前驱节点的物理位置
        int preCurrentFree = getIndex(size - 1); //空闲节点的前驱节点的物理位置


        T oldValue =  list[index].data; //清楚待删节点中的值
        list[index].data = null;

        //释放待删节点的物理位置
        if(position == 0){  //待删节点为头节点
            head = list[index].cur;
            list[preCurrentFree].cur = index;
            list[index].cur = currentFree;
            currentFree = index;
        }else if(position == size - 1){ //待删节点为尾节点
            currentFree = index;
        }else{
            preIndex = getIndex(position - 1);
            list[preIndex].cur = list[index].cur;
            list[preCurrentFree].cur = index;
            list[index].cur = currentFree;
            currentFree = index;
        }

        size--;
        return oldValue;
    }

    /**
     * 修改链表指定逻辑位置节点
     * @param position
     * @param data
     * @return
     */
    public T Set(int position, T data) {
        if (position < 0 || position >= size) {
            throw new IndexOutOfBoundsException("索引越界");
        }

        int index = getIndex(position);
        T oldValue = list[index].data;
        list[index].data  = data;

        return  oldValue;
    }

    /**
     * 按照静态链表的逻辑顺序打印所有节点信息
     * @return
     */
    @Override
    public String toString() {
        if (size == 0){
            return "{}";
        }

        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            sb.append("{链表中的位置position:" + i + ", 数据data:" + get(i).data + ", 在数组中的位置index:" + getIndex(i) + ", 游标cur:" + get(i).cur + "},\n");

        }
        sb.replace(sb.length() - 2, sb.length(), "]");
        return sb.toString();
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        StaticList<String> list = new StaticList();
        int num = list.DEFAUL_SIZE - 3;

        System.out.println("===========================添加数据=======================");
        for (int i = 0; i < num; i++) {
            list.add(i + "_" + i);
        }
        System.out.println(list.toString());

        System.out.println("===========================插入链表头结点=======================");
        list.add(0, "7_7");
        System.out.println(list.toString());


        System.out.println("===========================插入链表中间节点=======================");
        list.add(4, "8_8");
        System.out.println(list.toString());


        System.out.println("===========================插入链表的尾节点=======================");
        list.add(list.size - 1, "9_9");
        System.out.println(list.toString());

        System.out.println("===========================删除头结点=======================");
        list.delete(0);
        System.out.println(list.toString());

        System.out.println("===========================删除中间结点=======================");
        list.delete(4);
        System.out.println(list.toString());

        System.out.println("===========================删除中间结点=======================");
        list.delete(4);
        System.out.println(list.toString());


        System.out.println("===========================删除尾结点=======================");
        list.delete(list.size - 1);
        System.out.println(list.toString());

        System.out.println("===========================插入节点=======================");
        list.add("10_10");
        System.out.println(list.toString());

        System.out.println("===========================插入节点=======================");
        list.add("11_11");
        System.out.println(list.toString());

        System.out.println("===========================插入节点=======================");
        list.add("12_12");
        System.out.println(list.toString());

        System.out.println("===========================修改节点的值=======================");
        list.Set(list.size - 1, "12_12");
        System.out.println(list.toString());

    }

}

}

3 输出结果

  • 3.1 添加数据

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:3},
{链表中的位置position:3, 数据data:3_3, 在数组中的位置index:3, 游标cur:4},
{链表中的位置position:4, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:5, 数据data:5_5, 在数组中的位置index:5, 游标cur:6},
{链表中的位置position:6, 数据data:6_6, 在数组中的位置index:6, 游标cur:7}]

  • 3.2 插入链表头结

[{链表中的位置position:0, 数据data:7_7, 在数组中的位置index:7, 游标cur:0},
{链表中的位置position:1, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:2, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:3, 数据data:2_2, 在数组中的位置index:2, 游标cur:3},
{链表中的位置position:4, 数据data:3_3, 在数组中的位置index:3, 游标cur:4},
{链表中的位置position:5, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:6, 数据data:5_5, 在数组中的位置index:5, 游标cur:6},
{链表中的位置position:7, 数据data:6_6, 在数组中的位置index:6, 游标cur:8}]

  • 3.3 插入链表中间

[{链表中的位置position:0, 数据data:7_7, 在数组中的位置index:7, 游标cur:0},
{链表中的位置position:1, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:2, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:3, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:4, 数据data:8_8, 在数组中的位置index:8, 游标cur:3},
{链表中的位置position:5, 数据data:3_3, 在数组中的位置index:3, 游标cur:4},
{链表中的位置position:6, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:7, 数据data:5_5, 在数组中的位置index:5, 游标cur:6},
{链表中的位置position:8, 数据data:6_6, 在数组中的位置index:6, 游标cur:9}]

  • 3.4插入链表的尾节点

[{链表中的位置position:0, 数据data:7_7, 在数组中的位置index:7, 游标cur:0},
{链表中的位置position:1, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:2, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:3, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:4, 数据data:8_8, 在数组中的位置index:8, 游标cur:3},
{链表中的位置position:5, 数据data:3_3, 在数组中的位置index:3, 游标cur:4},
{链表中的位置position:6, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:7, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:8, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:9, 数据data:6_6, 在数组中的位置index:6, 游标cur:-1}]

  • 3.5删除头结点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:3},
{链表中的位置position:4, 数据data:3_3, 在数组中的位置index:3, 游标cur:4},
{链表中的位置position:5, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:6, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:7, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:8, 数据data:6_6, 在数组中的位置index:6, 游标cur:7}]

  • 3.6删除中间结点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:4},
{链表中的位置position:4, 数据data:4_4, 在数组中的位置index:4, 游标cur:5},
{链表中的位置position:5, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:6, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:7, 数据data:6_6, 在数组中的位置index:6, 游标cur:3}]

  • 3.7删除中间结点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:6, 数据data:6_6, 在数组中的位置index:6, 游标cur:4}]

  • 3.8删除尾结点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6}]

  • 3.9插入节点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:6, 数据data:10_10, 在数组中的位置index:6, 游标cur:4}]

  • 3.10插入节点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:6, 数据data:10_10, 在数组中的位置index:6, 游标cur:4},
{链表中的位置position:7, 数据data:11_11, 在数组中的位置index:4, 游标cur:3}]

  • 3.11插入节点

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:6, 数据data:10_10, 在数组中的位置index:6, 游标cur:4},
{链表中的位置position:7, 数据data:11_11, 在数组中的位置index:4, 游标cur:3},
{链表中的位置position:8, 数据data:12_12, 在数组中的位置index:3, 游标cur:7}]

  • 3.12修改节点的值

[{链表中的位置position:0, 数据data:0_0, 在数组中的位置index:0, 游标cur:1},
{链表中的位置position:1, 数据data:1_1, 在数组中的位置index:1, 游标cur:2},
{链表中的位置position:2, 数据data:2_2, 在数组中的位置index:2, 游标cur:8},
{链表中的位置position:3, 数据data:8_8, 在数组中的位置index:8, 游标cur:5},
{链表中的位置position:4, 数据data:5_5, 在数组中的位置index:5, 游标cur:9},
{链表中的位置position:5, 数据data:9_9, 在数组中的位置index:9, 游标cur:6},
{链表中的位置position:6, 数据data:10_10, 在数组中的位置index:6, 游标cur:4},
{链表中的位置position:7, 数据data:11_11, 在数组中的位置index:4, 游标cur:3},
{链表中的位置position:8, 数据data:12_12, 在数组中的位置index:3, 游标cur:7}]

4 参考文献

[1]程杰. 大话数据结构[M]. 清华大学出版社,2011

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值