【算法】Java-使用数组模拟单向链表,双向链表

这篇具有很好参考价值的文章主要介绍了【算法】Java-使用数组模拟单向链表,双向链表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

试题1:实现一个单链表,并实现以下功能:

试题2:实现一个双链表,并实现以下功能

思路总结:

什么情况下可能涉及到用数组实现链表呢?


      在学习时了解到了可以用数组模拟链表,使其兼顾数据查找快,链表新增和删除快的缺点,找来一些试题实现了下,如下:

试题1:实现一个单链表,并实现以下功能:

【算法】Java-使用数组模拟单向链表,双向链表,算法,算法,java,链表

Java代码实现:

import org.apache.commons.lang3.StringUtils;

import java.util.Scanner;

public class ArrayLinkedList {
    public static final int N = 100000;

    private int head; // head
    private int idx; // 存储新元素的索引下标
    private int[] e; // 存放数据的数组;
    private int[] ne; // 当前节点的下一个节点的地址(数组下标)。比如使用头插法,单向链表,e[5] = 5,e[5]的下一个节点的坐标是ne[5],下一个节点是e[ne[5]]

    public ArrayLinkedList() {
        e = new int[N];
        ne = new int[N];
        head = -1;
        idx = 0;
    }

    public void insertToHead(int val) {
        e[idx] = val;
        ne[idx] = head; // head的值是头结点指向的下一个元素的下标值
        head = idx++;
    }

    /**
     * 将val插入到索引k后面
     *
     * @param k
     * @param val
     */
    public void insert(int k, int val) {
        e[idx] = val;
        ne[idx] = ne[k];
        ne[k] = idx++;
    }

    /**
     * 删除k节点后面的节点(只删一个)
     *
     * @param k
     */
    public void remove(int k) {
        if (k + 1 == 0) {
            head = ne[head];
        } else {
            ne[k] = ne[ne[k]];
        }

    }

    public static void main(String[] args) {
        System.out.println("请输入:");
        Scanner scanner = new Scanner(System.in);
        ArrayLinkedList arrayLinkedList = new ArrayLinkedList();
        int head = arrayLinkedList.head;
        int[] e = arrayLinkedList.e;
        int[] ne = arrayLinkedList.ne;
        while (scanner.hasNextLine()) {
            String inputString = scanner.nextLine();
            if (StringUtils.isBlank(inputString)) {
                break;
            }
            String[] inputArr = inputString.split(" ");
            String f = inputArr[0];
            int s = Integer.valueOf(inputArr[1]);
            switch (f) {
                case "H":
                    arrayLinkedList.insertToHead(s);
                    break;
                case "D":
                    arrayLinkedList.remove(s - 1); // 第k个插入的数,idx是k-1
                    break;
                case "I":
                    int val = Integer.valueOf(inputArr[2]);
                    arrayLinkedList.insert(s - 1, val);
                    break;
            }
        }

        for (int i = head; i != -1; i = ne[i]) {
            System.out.print(e[i] + " ");
        }
        scanner.close();
    }
}

试题2:实现一个双链表,并实现以下功能

【算法】Java-使用数组模拟单向链表,双向链表,算法,算法,java,链表Java代码实现:

import org.apache.commons.lang3.StringUtils;

import java.util.Scanner;

/**
 * 支持的操作:
 * 1、在最左侧插入一个数;
 * 2、在最右侧插入一个数;
 * 3、将第k个插入的数删除;
 * 4、在第k个插入的数左侧插入一个数;
 * 5、在第k个插入的数右侧插入一个数
 */
public class TwoWayLinkedList2 {
    public static final int N = 100000;
    // 存放数组的数据
    private int[] e;
    // 存放左指针下标数组
    private int[] l;
    // 存放右指针地址数组
    private int[] r;
    // 数组待存储下标
    private int idx;
    // e[0]表示链表头;e[1]表示链表尾
    // 向左侧插入,就是插入到上一个节点的右侧。所以插入的逻辑都抽象成插入到具体节点的右侧

    // 构造方法
    public TwoWayLinkedList2() {
        e = new int[N];
        r = new int[N];
        l = new int[N];
        r[0] = 1;
        l[1] = 0;
        idx = 2;

    }

    /**
     * 将节点插入到e[k]节点右侧
     *
     * @param k
     * @param val
     */
    public void add(int k, int val) {
        e[idx] = val;
        l[idx] = k;
        r[idx] = r[k];
        l[r[k]] = idx;
        r[k] = idx;
        idx++;
    }

    /**
     * 删除e[k]
     *
     * @param k
     */
    public void remove(int k) {
        r[l[k]] = r[k];
        l[r[k]] = l[k];
    }

    public static void main(String[] args) {
        System.out.println("请输入:");
        Scanner scanner = new Scanner(System.in);
        TwoWayLinkedList2 linkedList = new TwoWayLinkedList2();
        int[] e = linkedList.e;
        int[] l = linkedList.l;
        int[] r = linkedList.r;
        while (scanner.hasNextLine()) {
            String inputString = scanner.nextLine();
            if (StringUtils.isBlank(inputString)) {
                break;
            }
            String[] inputArr = inputString.split(" ");
            String f = inputArr[0];
            Integer s = Integer.valueOf(inputArr[1]);

            switch (f) {
                case "L":
                    linkedList.add(0, s);
                    break;
                case "R":
                    linkedList.add(l[1], s);
                    break;
                case "D":
                    linkedList.remove(s + 1); // 第k个插入的数,idx是k+1,因为我们用了0和1表示链表头和链表尾
                    break;
                case "IL":
                    linkedList.add(l[s + 1], Integer.valueOf(inputArr[2]));
                    break;
                case "IR":
                    linkedList.add(s + 1, Integer.valueOf(inputArr[2]));
                    break;
            }
        }

        // 遍历输出
        for (int i = r[0]; i != 1; i = r[i]) {
            System.out.printf("" + e[i]);
        }
        scanner.close();
    }
}

思路总结:

       数组实现链表,一个数组用于存放数据,一个数组存放"指针",这里的指针用数组下标代替。如果是双向链表,要用两个数组存放指针。同时要注意首节点和尾结点的记录方法。在实现双链表时,我曾用两个变量表示首尾节点,对比起来,没有用e[0],e[1]表示简洁,而且非常容易搞混。占用第0位和第1位保存链表头和尾时要注意初始的idx=2,第k个插入的元素的索引下标是k+1。大家可以使用更多方法实现,过程虽然曲折,但一顿操作下来,对链表的操作会非常的熟练。

什么情况下可能涉及到用数组实现链表呢?

        在没有操作系统和内存管理的情况下。

1. 链表的实现需要动态内存分配和释放,这需要操作系统提供的堆内存管理。没有 OS 的动态内存管理,就无法真正实现链表节点的创建和销毁。

2. 链表通过指针链接节点,需要操作系统提供的指针和地址引用机制。没有 OS,就无法真正用指针建立节点之间的链接关系。

3. 数组可以预先分配一块内存,这个内存块可以视为堆内存,用下标代替指针,通过数组操作就可以模拟出指针操作。

4. 数组是一块连续的内存,空间固定,不需要动态扩展,所以定义数组后直接就可以使用,不依赖动态内存管理。

5. 数组中的每个元素是连续存储的,通过下标可以直接访问,不需要指针来进行寻址。可以模拟指针的移动,改变指针的指向来实现链表的操作。

        这里我们从算法分析和学习的角度来看这个问题,但不适合实际项目,只能处理规模较小的数据。要实现一个真正的可扩展链表,还需在操作系统上进行动态内存管理。文章来源地址https://www.toymoban.com/news/detail-707390.html

到了这里,关于【算法】Java-使用数组模拟单向链表,双向链表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构day06(单向循环链表、双向链表)

    双向链表的练习代码 head.h fun.c main.c 今日思维导图哈 ​​​​​​​

    2024年02月10日
    浏览(36)
  • openssl自签名CA根证书、服务端和客户端证书生成并模拟单向/双向证书验证

    1.1 生成CA证书私钥 openssl genrsa -aes256 -out ca.key 2048 1.2 取消密钥的密码保护 openssl rsa -in ca.key -out ca.key 1.3 生成根证书签发申请文件(csr文件) openssl req -new -sha256 -key ca.key -out ca.csr -subj \\\"/C=CN/ST=FJ/L=XM/O=NONE/OU=NONE/CN=localhost/emailAddress=test@test.com\\\" 上述参数含义 req----执行证书签发命令

    2024年04月25日
    浏览(42)
  • 【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)

    🍃 数据结构是 计算机 存储 、 组织 数据的方式 🎉 线性 结构 线性表(数组、链表、栈、队列、哈希表) 🎉 树形 结构 二叉树 AVL 树 红黑树 B 树 堆 Trie 哈夫曼树 并查集 🎉 图形 结构 邻接矩阵 邻接表 🎁 线性表是具有 n 个 相同类型元素 的有限 序列 (n = 0) a1 是首节点

    2024年02月10日
    浏览(77)
  • 数据结构与算法(三):单向链表

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑是通过链表种的指针链接次序实现的。链表由一系列节点组成,每个节点包括两部分:一个是存储数据元素的数据域,一个是存储下一个节点地址的指针域。单向链表从头节点(也可以没有头节点)开始

    2024年02月15日
    浏览(53)
  • [算法通关村] 1.1 单向链表的创建

    各位读者朋友们, 从今天开始,我将通过博文的形式,概述数据结构中应知必会的基本算法, 由于我更加熟悉 Java 语言,所以全程使用 Java 语言进行叙述, 如果您发现了文章中的错误,请您不吝赐教。         “链表”(Linked List)是一种常见的数据结构,用于存储和组

    2024年02月16日
    浏览(36)
  • 王道408用数组,链表以及双向链表实现栈、队列

    我在电脑上敲了一遍,又在纸上模拟了一遍 下面记录在电脑上敲的:    

    2024年02月14日
    浏览(36)
  • 王道408---用数组,链表以及双向链表实现栈、队列

    我在电脑上敲了一遍,又在纸上模拟了一遍 下面记录在电脑上敲的:    

    2024年02月14日
    浏览(32)
  • Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍   文章目录         1.0 队列的说明         1.1 队列的几种常用操作         2.0 使用链表实现队列说明         2.1 链表实现队列         2.2 链表实现队列 - 入栈操作         2.3 链表实现队

    2024年02月05日
    浏览(39)
  • Java 数据结构篇-用链表、数组实现栈

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍    文章目录         1.0 栈的说明         2.0 用链表来实现栈         2.1 实现栈 - 入栈方法(push)         2.2 实现栈 - 出栈(pop)         2.3 实现栈 - 查看栈顶元素(peek)         2.4 实

    2024年02月05日
    浏览(57)
  • 单向不带头链表的使用

    后插(将值为x的元素插入到第i个位置)  前插操作     画图时应先画物理结构图在画逻辑结构图  链表的结点查找 结点的创建

    2024年01月20日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包