Java数据结构之双端链表原理与实现方法

Java数据结构之双端链表原理与实现方法

一、什么是双端链表?

双端链表是一种链式数据结构,它每个节点都有两个指针:一个指向前一个节点,一个指向后一个节点。它具有链表的所有特点,而且还有一些独特的优点:对于一个双向链表,我们可以从头到尾遍历,也可以从尾到头遍历。在某些情况下,它比单向链表更有用,因为它可以执行逆序遍历。

二、双端链表的原理

双端链表由节点构成,每个节点包含两个引用/指针,一个指向前一个节点,指针称为"prev",一个指向后一个节点,指针称为"next"。如下图所示:

+------+    +------+    +------+
| data |    | data |    | data |
+------+    +------+    +------+
| prev |<-->| prev |<-->| prev |
+------+    +------+    +------+
| next |--> | next |--> | next |
+------+    +------+    +------+

双端链表有两个特殊节点:头节点和尾节点。头节点是链表的第一个节点,尾节点是链表的最后一个节点。头节点的"prev"指针指向"null",尾节点的"next"指针指向"null"。

三、双端链表的实现

3.1 双端链表节点的类定义

为了实现双端链表,我们需要定义一个节点类:

class Node<E> {
    E data;
    Node<E> prev;
    Node<E> next;

    public Node(E data, Node<E> prev, Node<E> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }
}

在这个节点类中,我们定义了一个泛型类型的数据成员"data"和两个引用类型的"prev"和"next",分别指向前一个节点和后一个节点。并实现了一个构造函数,用于创建一个新节点。

3.2 双端链表的类定义

双端链表的类定义如下:

public class DoubleLinkedList<E> {
    private Node<E> head;
    private Node<E> tail;
    private int size;

    public DoubleLinkedList() {
        head = null;
        tail = null;
        size = 0;
    }

    //添加新节点到链表尾部
    public void add(E element) {
        Node<E> newNode = new Node<E>(element, tail, null);
        if (tail != null) {
            tail.next = newNode;
        }
        tail = newNode;
        if (head == null) {
            head = newNode;
        }
        size++;
    }

    //获取指定下标的节点
    public Node<E> getNode(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
        Node<E> ptr = head;
        for (int i = 0; i < index; i++) {
            ptr = ptr.next;
        }
        return ptr;
    }

    //获取指定下标的节点的值
    public E get(int index) {
        return getNode(index).data;
    }

    //在指定节点后插入节点
    public void addAfter(Node<E> node, E element) {
        Node<E> newNode = new Node<E>(element, node, node.next);
        node.next = newNode;
        if (node == tail) {
            tail = newNode;
        } else {
            newNode.next.prev = newNode;
        }
        size++;
    }

    //在指定节点前插入节点
    public void addBefore(Node<E> node, E element) {
        Node<E> newNode = new Node<E>(element, node.prev, node);
        node.prev = newNode;
        if (node == head) {
            head = newNode;
        } else {
            newNode.prev.next = newNode;
        }
        size++;
    }

    //移除指定节点
    public void remove(Node<E> node) {
        if (node == head) {
            head = node.next;
        } else {
            node.prev.next = node.next;
        }
        if (node == tail) {
            tail = node.prev;
        } else {
            node.next.prev = node.prev;
        }
        size--;
    }
}

在这个双端链表类中,我们定义了三个数据成员:

  • "head" – 链表的第一个节点的引用。如果链表为空,则为"null"。
  • "tail" – 链表的最后一个节点的引用。如果链表为空,则为"null"。
  • "size" – 链表中节点的数量。

我们实现了五个公共方法:

  • "add" – 在链表的末尾添加一个新节点。
  • "getNode" – 获取给定索引处的节点。该方法用于支持其他方法的实现。
  • "get" – 获取给定索引处节点的值。
  • "addAfter" – 在给定节点的后面添加新节点。
  • "addBefore" – 在给定节点的前面添加新节点。
  • "remove" – 从链表中移除给定的节点。

以上这些方法以及节点类的定义可以满足双端链表的基本操作。

3.3 双端链表的使用示例

public class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList<String> list = new DoubleLinkedList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        Node<String> secondNode = list.getNode(1);
        list.addAfter(secondNode, "PHP");
        list.addBefore(secondNode, "JavaScript");

        Node<String> thirdNode = list.getNode(2);
        list.remove(thirdNode);

        System.out.println("Size of List : " + list.size);
        System.out.println("Head of List : " + list.head.data);
        System.out.println("Tail of List : " + list.tail.data);
        for (int i = 0; i < list.size; i++) {
            System.out.println("Data at Index " + i + " : " + list.get(i));
        }
    }
}

在这个示例中,我们向双端链表中插入三个元素("Java", "Python", "C++")。然后,在第二个元素后面添加"PHP",在第二个元素前面添加"JavaScript"。最后,从链表中删除第三个元素("C++")。最后打印链表的大小、头元素,尾元素和所有元素。

输出结果如下:

Size of List : 3
Head of List : JavaScript
Tail of List : Python
Data at Index 0 : JavaScript
Data at Index 1 : Java
Data at Index 2 : PHP

四、总结

双端链表是一种链式数据结构,具有许多链表的优点,它之所以称为"双向",是因为每个节点都有两个指针指向前一个节点和后一个节点。这使得它能够执行双向遍历。实现双端链表需要定义一个节点类以及一个双端链表类,同时实现一些基本操作如"添加"、"获取"、"插入"和"删除"等。以上内容是双端链表的基本原理和实现方法的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之双端链表原理与实现方法 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • AtCoder Beginner Contest 300

    A – N-choice question (abc300 a) 题目大意 给定一个元素互不相同的数组\(c\)和 \(a,b\),找到 \(i\)使得 \(c_i = a + b\) 解题思路 直接for循环寻找即可。 神奇的代码 #include <bits/stdc++.h> using namespace std; using LL = …

    算法与数据结构 2023年4月30日
    00
  • C语言编程简单却重要的数据结构顺序表全面讲解

    C语言编程简单却重要的数据结构顺序表全面讲解 什么是顺序表? 顺序表是一种线性表,指的是一组有限元素的有限序列,其元素的逻辑顺序与它们在分配到的内存地址上的物理顺序相同或者等价。也就是说,顺序表中的元素按照其在内存中的位置依次存放。 顺序表的实现方式 顺序表的实现方式一般是使用数组,数组中的每一个元素对应着顺序表中的一个元素,位置相对应。 顺序表的优点 支持…

    数据结构 2023年5月17日
    00
  • 常用的Java数据结构知识点汇总

    常用的Java数据结构知识点汇总 简介 Java中的数据结构是Java程序开发中非常重要的一部分。掌握常用的数据结构知识点是编写高效、优秀的Java程序的关键之一。本文将详细讲解Java中常用的数据结构知识点,并提供代码示例说明。 数组(Array) 数组是一组相同类型的数据集合,通过数组下标来访问数据,数组长度确定后就无法改变。在Java中,数组可以是基本…

    数据结构 2023年5月17日
    00
  • 排序算法之详解冒泡排序

    引入 冒泡排序顾名思义,就是像冒泡一样,泡泡在水里慢慢升上来,由小变大。 虽然冒泡排序和冒泡并不完全一样,但却可以帮助我们理解冒泡排序。 思路 一组无序的数组,要求我们从小到大排列 我们可以先将最大的元素放在数组末尾 再将第二大的数放在数组的倒数第二个位置 再将第三大的数放在数组的倒数第三个位置 以此类推 那么现在问题的关键就是如何将 第 n 大的数 放在 …

    算法与数据结构 2023年4月25日
    00
  • 自学1

    Problem1 明明的随机数 ## 题目描述 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 (N <= 100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“…

    算法与数据结构 2023年4月24日
    00
  • 「学习笔记」AC 自动机

    「学习笔记」AC 自动机 点击查看目录 目录 「学习笔记」AC 自动机 算法 问题 思路 代码 例题 Keywords Search 玄武密码 单词 病毒 最短母串 文本生成器 背单词 密码 禁忌 前置:「学习笔记」字符串基础:Hash,KMP与Trie。 好像对例题的讲解越来越抽象了? 算法 问题 求 \(n\) 个单词在一个长度为 \(m\) 的文章里出…

    算法与数据结构 2023年5月5日
    00
  • C语言单链队列的表示与实现实例详解

    C语言单链队列的表示与实现实例详解 什么是队列? 在计算机科学中,队列(Queue)是一种特殊的数据结构,它只允许在一端进行插入操作,在另一端进行删除操作。将新元素插入队列的过程可以称之为入队,而将元素从队列中删除的过程则可以称之为出队。队列的核心思想是“先进先出”(First In First Out,FIFO),即先入队的元素先出队。 单链队列的表示方式…

    数据结构 2023年5月17日
    00
  • JavaScript数据结构与算法之二叉树遍历算法详解【先序、中序、后序】

    JavaScript数据结构与算法之二叉树遍历算法详解 什么是二叉树 二叉树是一种每个节点最多只有两个子节点的树结构,可以用来组织数据、搜索、排序等。 二叉树的遍历 遍历是指按照一定次序访问二叉树中的所有节点。常见的二叉树遍历有三种方式:先序遍历、中序遍历、后序遍历。以下分别对它们进行详细讲解。 前序遍历 前序遍历是指先访问节点本身,然后再遍历其左子树和右子…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部