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数据结构之堆(优先队列)详解

    Java数据结构之堆(优先队列)详解 概述 堆是一种基于树的数据结构,它可以用来解决很多问题,例如排序、优先队列等。在堆中,每个节点的值都小于或等于它的子节点的值。堆分为两种类型:最大堆和最小堆。在最大堆中,根节点的值最大;而在最小堆中,根节点的值最小。 堆的操作主要有以下两种: 插入:将一个元素插入到堆中,需要维护堆的性质,即节点的值小于或等于子节点的值。…

    数据结构 2023年5月17日
    00
  • Android开发数据结构算法ArrayList源码详解

    Android开发数据结构算法ArrayList源码详解 概述 Android开发中,大量使用到了数据结构和算法,ArrayList便是其中的一种非常重要的数据结构。ArrayList是Java中非常重要且使用率非常高的一种数据结构,Android开发中也经常使用它来存储数据。本文将深入探究ArrayList的源码,帮助读者更好地理解其工作原理和使用方法。 …

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

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

    数据结构 2023年5月17日
    00
  • JavaScript数据结构Number

    JavaScript数据结构Number 简介 JavaScript中的Number是一种表示数字的数据类型,包括整数和浮点数。Number类型的值是不可变的。 数字类型(Number)的创建 数字类型可以通过直接赋值的方式创建,如: let num = 10; // 整数 let floatNum = 3.14; // 浮点数 另外,JavaScript还…

    数据结构 2023年5月17日
    00
  • 深入解析MySQL索引数据结构

    深入解析MySQL索引数据结构 MySQL索引是优化查询效率的重要一环,本文将深入解析MySQL索引数据结构,帮助读者理解MySQL索引原理,并通过两个示例说明不同类型的索引在实际应用中的效果。 索引数据结构 MySQL支持两种类型的索引数据结构:B-Tree索引和Hash索引。 B-Tree索引 B-Tree索引是MySQL常用的索引类型,用于优化WHER…

    数据结构 2023年5月17日
    00
  • EMI/EMS/EMC有什么关系?

    EMI(Electromagnetic Interference)直译是“电磁干扰”,是指电子设备(即干扰源)通过电磁波对其他电子设备产生干扰的现象。 从“攻击”方式上看,EMI主要有两种类型:传导干扰和辐射干扰。 电磁传导干扰是指干扰源通过导电介质(例如电线)把自身电网络上的信号耦合到另一个电网络。 电磁辐射干扰往往被我们简称为电磁辐射,它是指干扰源通过空…

    算法与数据结构 2023年4月17日
    00
  • Java数据结构之优先级队列(PriorityQueue)用法详解

    Java数据结构之优先级队列(PriorityQueue)用法详解 什么是优先级队列? 优先级队列(Priority Queue)是一种特殊的队列,它能够保证每次取出的元素都是优先级最高(或者最低)的元素。在实际应用中,优先级队列经常用来实现任务调度,负载均衡等。 Java中的优先级队列 在Java中,优先级队列实现了Queue接口,所以它也具有队列的基本特…

    数据结构 2023年5月17日
    00
  • C语言实现通用数据结构之通用椎栈

    C语言实现通用数据结构之通用椎栈 概述 通用椎栈(Generic Linked List Stack),简称GLL Stack,是一种通用的数据结构,能够以动态的方式存储和访问任意类型的数据。GLL Stack 采用链表实现,可以进行进栈(push)、出栈(pop)、查看栈顶元素(peek)、判断栈是否为空(isEmpty)等基本操作。 基本操作 数据结构定…

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