数据结构_数组模拟链表

1、数组模拟单链表

1.1图示

  • 原先的单链表都是一个个的Node节点,Node有data域和next域,每一个Node都是一个单独的对象,每一个Node使用next关联起来形成一个链表。
  • 现在使用数组模拟链表,我们使用两个数组,一个E[]数组,存储的是data,一个Ne[]数组,存储当前节点的下一个节点的索引值。如下图所示。并且使用两个指针,一个是head指针,指向头结点(非虚拟头结点,这里是第一个节点),一个是idx指针,指向待插入节点的位置, 注意:最后一个节点的next为-1

在这里插入图片描述

1.2代码实现

1.2.1初始化

初始化时我们需要先创建两个数组,和两个指针(索引),head置为-1,idx置为0

此时链表中还没有节点,所以head指向-1。

因为idx指向的是待插入节点的位置,当链表为空时,待插入的节点就是第一个位置,即索引为0

 public class ArrayLinkedList{
    
    
    static int[] e;
    static int[] next;

    //头结点的索引
    static int head;
    //待插入节点的索引
    static int idx;

    static void init() {
    
    
        e = new int[10010];
        next = new int[10010];
        head = -1;
        idx = 0;
    }
 }

1.2.3头插法

在链表的头部添加一个节点

    static void addHead(int data) {
    
    
        e[idx] = data;       //为新节点的data域赋值
        next[idx] = head;   //将新节点的next指向原来的头结点 刚开始时head是-1,
        					//所以第一个节点的next就是-1 最后一个节点的next总是-1
        					//遍历时可以作为终止条件
        head = idx;        //将head指向新的头结点head
        idx++;            //idx++ 继续指向待插入节点的位置
    }

1.2.3在索引为k的节点后插入一个节点

跟普通的链表的插入都是类似的,先将待插入节点指向原节点的next,然后将原节点指向待插入节点

static void insertAfter(int k ,int data){
    
    
     e[idx] = data;      //为新节点的data域赋值
     ne[idx] = ne[k];    //新节点的next指向原第k个节点的next
     ne[k] = idx;        //第k个节点的next指向新节点
     idx++;               //idx++ 继续指向待插入节点的位置
}

1.2.4删除索引为k的节点的后面的一个节点

static void delAfter(int k){
    
    
    //删除的是头结点 就将头节点指向下一个节点
    if(k==0)head = ne[head];
    //不是头结点 就将k索引的直接指向k后面的第二个节点
    else ne[k] = ne[ne[k]];        
}

1.2.5遍历

这里的终止条件就是某一个节点的next为-1

for (int i = head; i != -1; i = ne[i]){
    
    
    System.out.println(e[i]);
} 

1.3练习

AcWing826.单链表

2、数组模拟双向链表

2.1图示

数组模拟双向链表和模拟单链表类似,只是多了一个数组,存储的是上一个节点的索引,而且我们为了不考虑边界问题,将索引为0的节点作为整个链表的左边界,将索引为1的节点作为整个链表的右边界,只考虑删除和插入即可,idx指针还是指向待插入位置的索引
在这里插入图片描述

2.2代码示例

2.2.1初始化

根据上面的分析,这里要使用三个数组

public class DoubleArrayLinkedList {
    
    
    static int[] e;
    static int[] l;
    static int[] r;

    //待插入节点的索引
    static int idx;

    static void init() {
    
    
        e = new int[10010];
        l = new int[10010];
        r = new int[10010];
        l[1] = r[0];
        r[0] = l[1];
        //因为0和1代表左右边界,所以idx第一次指向2的位置
        idx = 2;
    }
}

2.2.2在第k个插入的节点后插入一个节点

    static void insertAfter(int k, int data) {
    
    
        e[idx] = data;
        //先将第k个插入的节点的右边的节点整好双向连上新节点
        r[idx] = r[k];
        l[r[k]] = idx;
        //将第k个插入的节点双向连上新节点
        r[k] = idx;
        l[idx] = k;
        idx++;
    }

2.2.3删除插入的第k个节点

static void remove(int k) {
    
    
    //k的右边的左边等于k的左边
    l[r[k]] = l[k];
    //k的左边的右边等于k的右边
    r[l[k]] = r[k];
}

2.2.4遍历

从索引为0的位置开始遍历,当遍历到索引为1时终止

扫描二维码关注公众号,回复: 13358457 查看本文章
        for(int i = r[0];i!=1;i=r[i]){
    
    
            System.out.println(e[i]);
        }

2.3练习

AcWing827.双向链表

猜你喜欢

转载自blog.csdn.net/qq_46312987/article/details/119785065