java数据结构之实现双向链表的示例

Java数据结构之实现双向链表的示例

1. 什么是双向链表?

双向链表,英文名为doubly linked list,是一种链表结构。与单向链表不同,双向链表中的每一个节点除了保存了指向下一个节点的指针外,还保存了指向前一个节点的指针。因此,双向链表可双向遍历,可以从前向后或从后向前遍历。

2. 双向链表的实现

2.1 节点类的实现

创建节点类Node,并定义节点的属性和方法。

public class Node<E> {
    private E data; // 数据
    private Node<E> prev; // 前一个节点
    private Node<E> next; // 后一个节点

    // 构造方法
    public Node(E data, Node<E> prev, Node<E> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }

    // setter和getter方法
    public void setData(E data) {
        this.data = data;
    }

    public E getData() {
        return data;
    }

    public void setPrev(Node<E> prev) {
        this.prev = prev;
    }

    public Node<E> getPrev() {
        return prev;
    }

    public void setNext(Node<E> next) {
        this.next = next;
    }

    public Node<E> getNext() {
        return next;
    }
}

在构造方法中初始化节点的属性,setData()和getData()方法用于设置和获取节点的数据,setPrev()和getPrev()方法用于设置和获取前一个节点,setNext()和getNext()方法用于设置和获取后一个节点。

2.2 双向链表类的实现

创建双向链表类DoublyLinkedList,并定义双向链表的属性和方法。

public class DoublyLinkedList<E> {
    private Node<E> head; // 头节点
    private Node<E> tail; // 尾节点
    private int size = 0; // 链表长度

    // 构造方法
    public DoublyLinkedList() {
        head = null;
        tail = null;
    }

    // 获取链表长度
    public int size() {
        return size;
    }

    // 判断链表是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    // 向链表尾部添加节点
    public void add(E data) {
        addLast(data);
    }

    // 向链表尾部添加节点
    public void addLast(E data) {
        Node<E> newNode = new Node<E>(data, tail, null);
        if (tail == null) { // 链表为空时,新节点既是头节点又是尾节点
            head = newNode;
            tail = newNode;
        } else {
            tail.setNext(newNode);
            tail = newNode;
        }
        size++;
    }

    // 向链表头部添加节点
    public void addFirst(E data) {
        Node<E> newNode = new Node<E>(data, null, head);
        if (head == null) { // 链表为空时,新节点既是头节点又是尾节点
            head = newNode;
            tail = newNode;
        } else {
            head.setPrev(newNode);
            head = newNode;
        }
        size++;
    }

    // 获取链表中指定位置的节点
    public Node<E> getNode(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
        Node<E> node = head;
        for (int i = 0; i < index; i++) {
            node = node.getNext();
        }
        return node;
    }

    // 获取链表中指定位置节点的数据
    public E get(int index) {
        return getNode(index).getData();
    }

    // 修改链表中指定位置节点的数据
    public void set(int index, E data) {
        Node<E> node = getNode(index);
        node.setData(data);
    }

    // 在链表中指定位置插入节点
    public void add(int index, E data) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
        if (index == 0) {
            addFirst(data);
        } else if (index == size) {
            addLast(data);
        } else {
            Node<E> oldNode = getNode(index);
            Node<E> newNode = new Node<E>(data, oldNode.getPrev(), oldNode);
            oldNode.getPrev().setNext(newNode);
            oldNode.setPrev(newNode);
            size++;
        }
    }

    // 删除链表中指定位置节点
    public void remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
        if (index == 0) {
            head = head.getNext();
            if (head != null) {
                head.setPrev(null);
            } else {
                tail = null;
            }
        } else if (index == size - 1) {
            tail = tail.getPrev();
            if (tail != null) {
                tail.setNext(null);
            } else {
                head = null;
            }
        } else {
            Node<E> oldNode = getNode(index);
            oldNode.getPrev().setNext(oldNode.getNext());
            oldNode.getNext().setPrev(oldNode.getPrev());
            oldNode.setData(null);
        }
        size--;
    }
}

在构造方法中初始化链表的头节点和尾节点,size()方法用于获取链表长度,isEmpty()方法用于判断链表是否为空。add()、addLast()、addFirst()方法用于向链表中添加节点,getNode()方法用于获取链表中指定位置的节点,get()方法用于获取链表中指定位置节点的数据,set()方法用于修改链表中指定位置节点的数据,add()方法用于在链表中指定位置插入节点,remove()方法用于删除链表中指定位置节点。

3. 示例说明

3.1 示例一:创建双向链表并向其中添加数据

public static void main(String[] args) {
    DoublyLinkedList<String> list = new DoublyLinkedList<String>();
    list.addLast("A");
    list.addLast("B");
    list.addFirst("C");
    list.add(1, "D");
    System.out.println(list.get(0)); // output: C
    System.out.println(list.get(1)); // output: D
    System.out.println(list.get(2)); // output: A
    System.out.println(list.get(3)); // output: B
}

首先创建一个DoublyLinkedList对象list,并向其中添加数据。addLast()方法将"A"和"B"分别添加到链表尾部,addFirst()方法将"C"添加到链表头部,add()方法将"D"插入到链表中间位置。最后输出链表中各个位置的数据。

3.2 示例二:在双向链表中删除节点

public static void main(String[] args) {
    DoublyLinkedList<String> list = new DoublyLinkedList<String>();
    list.addLast("A");
    list.addLast("B");
    list.addFirst("C");
    list.add(1, "D");
    System.out.println(list.get(2)); // output: A
    System.out.println(list.size()); // output: 4
    list.remove(2);
    System.out.println(list.get(2)); // output: D
    System.out.println(list.get(3)); // output: B
    System.out.println(list.size()); // output: 3
}

首先创建一个DoublyLinkedList对象list,并向其中添加数据。addLast()方法将"A"和"B"分别添加到链表尾部,addFirst()方法将"C"添加到链表头部,add()方法将"D"插入到链表中间位置。然后删除链表中第2个位置的数据,最后输出链表中各个位置的数据和链表长度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java数据结构之实现双向链表的示例 - Python技术站

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

相关文章

  • Java数据结构之KMP算法的实现

    Java数据结构之KMP算法的实现 1. KMP算法的概述 KMP算法的全称是Knuth-Morris-Pratt算法,是一种字符串匹配算法,用于在文本串S内查找一个模式串P的出现位置。它的特点是在P和S两个序列中,当匹配失败时,它会跳过P的部分已匹配的字符,利用这个信息来减少S和P之间的匹配次数,从而提高匹配效率。 2. KMP算法的实现 2.1 预处理失…

    数据结构 2023年5月17日
    00
  • C语言数据结构 栈的基础操作

    C语言数据结构 栈的基础操作 1. 栈的基本概念 栈(Stack)是一种基于LIFO(后进先出)原理的数据结构,类似于一组盘子,只能在盘子的顶部进行操作。每次从顶部添加或移除盘子。 栈具有两个基本操作:入栈(push)和出栈(pop)。当添加一个元素时,我们称其为“push”,当移除一个元素时,我们称其为“pop”。 2. 栈的实现 栈可以使用数组或链表来实…

    数据结构 2023年5月17日
    00
  • C#数据结构之堆栈(Stack)实例详解

    C#数据结构之堆栈(Stack)实例详解 在编程中,我们经常需要保存一些数据,这些数据可以根据其进入的先后顺序以及其他规则进行处理和访问。其中,堆栈(Stack)是一种简单但是非常有用的数据结构。本文将为大家详细讲解堆栈(Stack)的概念、用法以及C#中的实现方法。 堆栈(Stack)概述 堆栈(Stack)是一种后进先出(LIFO)的数据结构。也就是说,…

    数据结构 2023年5月17日
    00
  • Codeforces Round 871 (Div. 4)

    A.Love Story 题意: 给定n个长度为10的字符串,问其与codeforces字符串的对应下标字母不同的个数。 分析: 对于每个字符串从前往后依次和“codeforces”对应字符比较然后统计不同字母数即可 code: #include <bits/stdc++.h> using namespace std; int main() { …

    算法与数据结构 2023年5月8日
    00
  • Java数据结构之图(动力节点Java学院整理)

    Java数据结构之图是动力节点Java学院整理的一篇关于图的攻略教程,该教程包含以下主要内容: 一、图的定义 图是由若干个顶点以及它们之间的相互关系所构成的数学模型。它包含了许多实际生活中的应用,如社交网络、地图、电子邮件网络等。 二、图的存储方式 图的存储方式有两种:邻接矩阵和邻接表。 邻接矩阵 邻接矩阵以二维数组的形式存储图。对于有n个顶点的图,其邻接矩…

    数据结构 2023年5月17日
    00
  • JS中的算法与数据结构之链表(Linked-list)实例详解

    JS中的算法与数据结构之链表(Linked-list)实例详解 什么是链表? 链表是计算机科学中的一种数据结构,由一系列结点(Link,也称为节点)组成,并通过每个节点中的指针(Pointer)链接在一起。每个节点包含数据和一个指向某个位置的引用。 链表的主要特点是在插入和删除操作中表现出很高的效率。与数组相比,链表的访问和操作速度较慢,但在处理动态结构数据…

    数据结构 2023年5月17日
    00
  • Java数据结构之对象的比较

    Java数据结构之对象的比较 在Java中,对象的比较是非常重要的操作。我们常常需要对不同的对象进行比较,以便对它们进行排序、按照某个条件过滤等操作。本文将详细讲解Java中对象的比较,并给出一些示例来说明。 对象的比较方法 Java中有两种对象比较方法:值比较和引用比较。值比较就是比较两个对象的值是否相等,而引用比较是比较两个对象是否是同一个对象。 值比较…

    数据结构 2023年5月17日
    00
  • JavaScript 数据结构之散列表的创建(2)

    下面是详细讲解“JavaScript 数据结构之散列表的创建(2)”的完整攻略。 散列表(哈希表) 散列表是一种数据结构,使用哈希函数将键映射到索引。散列表可以在常量时间 O(1) 中进行插入、删除和查找操作,但也具有碰撞冲突问题。 碰撞冲突问题 在散列表中,当两个不同的键通过哈希函数映射到了同一个索引位置时,就会发生碰撞冲突问题。解决碰撞冲突问题的方法有很…

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