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日

相关文章

  • 「双端队列BFS」电路维修

    本题为3月23日23上半学期集训每日一题中B题的题解 题面 题目描述 Ha’nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。 电路板的整体结构是一个R行C列的网格( \(R,C \leq 500\) ),如右图所示。每个格点都是…

    算法与数据结构 2023年4月18日
    00
  • Java数据结构之顺序表篇

    Java数据结构之顺序表篇 什么是顺序表 顺序表是由一组地址连续、大小相等的存储单元依次存储数据元素的线性表。 顺序表的表示 Java语言中,可以使用数组来表示顺序表。 public class SeqList<T> { private Object[] element;// 定义数组存储数据元素 private int length;// 当前…

    数据结构 2023年5月17日
    00
  • 举例讲解C语言程序中对二叉树数据结构的各种遍历方式

    那么我们先来介绍一下二叉树。 什么是二叉树? 二叉树是一种树状的数据结构,它的每个节点最多有两个子节点,分别称为左子节点和右子节点。二叉树节点的定义如下: typedef struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NUL…

    数据结构 2023年5月17日
    00
  • C#数据结构之队列(Quene)实例详解

    C#数据结构之队列(Quene)实例详解 什么是队列? 队列是一种线性数据结构,只允许在队列的两端进行操作。队列是一种FIFO(First in First Out)的数据结构,即先进先出,类似于排队买票的场景。 C#中的队列(Quene) C#中队列(Quene)是System.Collections命名空间中的一个类,可以通过引入System.Colle…

    数据结构 2023年5月17日
    00
  • JavaScript的Set数据结构详解

    JavaScript中的Set数据结构详解 什么是Set? Set 是一种 Javascript 内置的数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,可以通过new关键字来创建 Set 数据结构。 let mySet = new Set(); Set的基本用法 Set实例对象有以下常用方法: add(value):…

    数据结构 2023年5月17日
    00
  • 详解C语言实现空间索引四叉树

    详解C语言实现空间索引四叉树攻略 四叉树是一种常见的空间索引方法,可以有效地处理二维或三维空间中的数据。本攻略将详细介绍使用C语言实现空间索引四叉树的方法,包括数据结构的设计,插入和查询操作的实现。 数据结构设计 结点结构体 struct QuadtreeNode { int depth; // 结点深度 double x, y; // 结点中心坐标 dou…

    数据结构 2023年5月17日
    00
  • C++数据结构深入探究栈与队列

    C++数据结构深入探究栈与队列 简介 栈和队列是常见的数据结构,尤其在程序设计和算法中都是不可或缺的。本文将深入讲解C++中栈和队列的实现原理和基本操作,并提供两个示例说明其应用。 栈(Stack)基本操作 栈的定义 栈是一种线性数据结构,具有后进先出(Last In First Out, LIFO)的特点。栈可以用数组或链表实现。 栈的操作 push() …

    数据结构 2023年5月17日
    00
  • C语言数据结构深入探索顺序表

    C语言数据结构深入探索顺序表攻略 一、概述 顺序表是一种线性结构,是计算机程序中最常见的数据结构之一。在C语言中,顺序表可以用数组来实现。本篇文章将深入讲解顺序表的原理和实现方法,帮助读者加深对顺序表的理解,并掌握如何用C语言代码实现顺序表。 二、顺序表的定义和特点 顺序表是指用一组地址连续的存储单元依次存储线性表中的各个元素,用于表示具有相同数据类型的n个…

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