算法-链表(数组实现)

为什么要用数组进行链表模拟

在Java中我们可以创建Node节点通过创建新节点 new Node() 的方式模拟链表实现,但是每一次都需要创建新节点,是比较慢的,而我们用数组进行模拟链表较快。

而链表又分为单链表和双链表,具体来看看如何用数组进行单、双链表的模拟。

单链表

用法:

单链表用得较多的是邻接表 ——> 存储图和树。

需要什么:

1.需要存储值的数组e[N];
2.下一个的指针数组ne[N];
3.尾指针指向空,则ne[i] = -1;
!值数组n[N]和指针数组ne[N]是通过下标联系起来的!

详解:怎么写单链表

注意:head指的是节点的下标,idx为当前操作值的下标。这两个在刚开始理解可能较困难 ,在此单列出来。

1.进行初始化
在这里插入图片描述
初始化需要注意头节点为空,并且让idx从0开始。

2.把 x插入为第一个元素
在这里插入图片描述
3.把x点插入到下标为k的点的后面
在这里插入图片描述
4.删除k后面的点
在这里插入图片描述

题目:

在这里插入图片描述
在这里插入图片描述

解题完整代码 (Java)

import java.util.Scanner;

public class Main {
    static int head;//head表示头结点的下标
    static int N = 100010;
    static int[] e = new int[N];//e[i]表示结点i的值
    static int[] ne = new int[N];//ne[i]表示结点i的next指针是多少
    static int idx;//存储当前值的下标

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int M = sc.nextInt();
        //首先进行初始化
        init();
        while (M-- > 0) {
            String s = sc.next();
            char op = s.charAt(0);
            if (op == 'H') {
                int x = sc.nextInt();
                add_to_head(x);
            } else if (op == 'D') {
                int k = sc.nextInt();
                //k为0时,删除头节点
                if (k == 0) {
                    head = ne[head];//删除头节点就是让原先头节点的下标变成原先头节点下一个结点的下标
                } else {
                    remove(k - 1);
                }
            } else {
                int k = sc.nextInt();
                int x = sc.nextInt();
                add(k - 1, x);
            }
        }
        for (int i = head; i != -1; i = ne[i]) {//由于头节点可能会改变,遍历的起始值为头结点的下标head
            System.out.print(e[i] + " ");
        }
    }

    //初始化
    public static void init() {
        head = -1;//初始化时,头结点为空
        idx = 0;//idx从0号点开始分配
    }

    //把x插入到头结点上
    public static void add_to_head(int x) {
        e[idx] = x;
        ne[idx] = head;
        head = idx;
        idx++;
    }

    //将x点插入到下标为k的点的后面
    public static void add(int k, int x) {
        e[idx] = x;
        ne[idx] = ne[k];
        ne[k] = idx;
        idx++;
    }

    //删除k后面的点
    public static void remove(int k) {
        ne[k] = ne[ne[k]];
    }

}

双链表

用法:

双链表较多用于某些问题的优化。
特点:双链表有两个指针,一个指向前,一个指向后。

需要什么:

1.存储节点值的数组:e[N];
2.存储e[i]上一个点的下标:l[N];
3.存储e[i]下一个点的下标:r[N];
3.存储当前值的下标:idx
双链表值数组和指针数组也是通过下标联系起来的。

详解:怎么写双链表

1.进行初始化
在这里插入图片描述
2.在下标为k的点的右边(下一个)插入x
在这里插入图片描述
注意在左边(上一个)插入x,就是在l[k]的后面插入x,进行转换。
3.删除下标为k的点
在这里插入图片描述

题目:

在这里插入图片描述
在这里插入图片描述

解题完整代码(Java)

import java.util.Scanner;

public class Main {
    static int N = 100010;
    static int[] e = new int[N];//e[i]表示结点i的值
    static int[] l = new int[N];//存储e[i]上一个点的下标
    static int[] r = new int[N];//存储e[i]下一个点的下标
    static int idx;//存储当前值的下标

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int M = sc.nextInt();
        init();
        while (M-- > 0){
            String s = sc.next();
            char op = s.charAt(0);
            if(op =='L'){
                int x = sc.nextInt();
                add(0,x);
            }else if(op =='R'){
                int x = sc.nextInt();
                add(l[1],x);
            }else if(op =='D'){
                int x = sc.nextInt();
                remove(x+1);
            }else if(s.equals("IR")){
                int k = sc.nextInt();
                int x = sc.nextInt();
                add(k+1,x);
            }else {
                int k = sc.nextInt();
                int x = sc.nextInt();
                add(l[k+1],x);
            }
        }
        for (int i = r[0]; i != 1 ; i=r[i]) {
            System.out.print(e[i] + " ");
        }
    }
    //初始化
    public static void init(){
        //0表示左端点,1表示右端点
        r[0] = 1;
        l[1] = 0;
        idx = 2;//0和1已经被占用了
    }
    //在下标为k的点的右边插入x
    public static void add(int k,int x){
        e[idx] = x;
        r[idx] = r[k];
        l[idx] = k;
        l[r[k]] = idx;
        r[k] = idx;
        idx++;//不要忘了idx在进行插入时要自增
        //在下标为k的点的左边插入x,就是在l[k]后面插入x
    }
    //删除下标为k的点
    public static void remove(int k){
        r[l[k]] = r[k];
        l[r[k]] = l[k];
    }
}

学习链表的时候,首先理解链表是要实现一个什么样的模型,本篇主要是关于数组如何进行模拟实现,理解之后抽出需要的方法,题目就是经过不同的包装,依具体题意分析,但是实现的基本功能是不变的。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,队列算法可以用链表实现,这种实现方式被称为链式队列(Linked Queue)。 链式队列使用链表来存储元素,不需要预先指定队列的容量,因此可以动态地增加或减少元素。链式队列有两个指针,一个指向队头,一个指向队尾,插入和删除元素只需要更新这两个指针即可。 下面是使用Java实现链式队列的算法代码: ```java public class LinkedQueue { private Node front; // 队头指针 private Node rear; // 队尾指针 // 节点类 private class Node { private int data; private Node next; public Node(int data) { this.data = data; } } // 构造方法,初始化队列 public LinkedQueue() { front = null; rear = null; } // 插入元素,从队尾插入 public void insert(int value) { Node newNode = new Node(value); if (rear == null) { front = newNode; rear = newNode; } else { rear.next = newNode; rear = newNode; } } // 删除元素,从队头删除 public int remove() { if (front == null) { throw new NoSuchElementException(); } int value = front.data; front = front.next; if (front == null) { rear = null; } return value; } // 判断队列是否为空 public boolean isEmpty() { return (front == null); } // 返回队列大小 public int size() { int count = 0; Node current = front; while (current != null) { count++; current = current.next; } return count; } } ``` 此代码实现了一个简单的链式队列,包括插入、删除、判断队列是否为空和返回队列大小等基本操作。需要注意的是,链式队列插入和删除元素只需要更新队尾指针和队头指针即可,不需要像数组实现那样移动元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值