Java数据结构之链表实现(单向、双向链表及链表反转)

Java数据结构之链表实现

链表基础概念

链表是一种数据结构,它由一系列节点(Node)组成,每个节点包含两个部分,一个是数据域(data),一个是指针域(next)。数据域存储数据信息,指针域指向下一个节点。

链表的种类很多,比如单向链表、双向链表、循环链表等等。

单向链表:链表的每个节点只有一个指针域,指向下一个节点。

双向链表:链表的每个节点有两个指针域,一个指向前一个节点,一个指向后一个节点。

循环链表:链表的最后一个节点指向链表的头节点。

单向链表的实现

定义单向链表节点类

定义单向链表的节点类Node,由data和next两部分组成,即数据和下一个节点的指针。

class Node {
    int data;
    Node next;

    public Node(int data) {
        this.data = data;
        this.next = null;
    }
}

单向链表的基本操作

单向链表的基本操作,包括增加节点、删除节点、遍历节点和获取链表长度等。

增加节点

在链表末尾添加一个节点,并使新节点成为新的末尾节点。

public void addNode(int data) {
    Node newNode = new Node(data);
    if (head == null) {    // 添加的节点为头节点
        head = newNode;
        return;
    }
    Node temp = head;
    while (temp.next != null) {
        temp = temp.next;
    }
    temp.next = newNode;
}

删除节点

删除链表中指定节点,需要找到该节点的前一个节点,使得前一个节点的指针指向后一个节点。

public void deleteNode(int data) {
    if (head == null) {    // 空链表
        return;
    }
    if (head.data == data) {   // 删除头节点
        head = head.next;
        return;
    }
    Node temp = head;
    while (temp.next != null && temp.next.data != data) {
        temp = temp.next;
    }
    if (temp.next == null) {  // 节点不存在
        return;
    }
    temp.next = temp.next.next; // 删除节点
}

遍历节点

遍历链表中的所有节点。

public void traverse() {
    Node temp = head;
    while (temp != null) {
        System.out.print(temp.data + "->");
        temp = temp.next;
    }
    System.out.println("null");
}

获取链表长度

获取链表的长度,需要从头节点开始遍历,同时计数器加1,直到遍历完成。

public int length() {
    int count = 0;
    Node temp = head;
    while (temp != null) {
        count++;
        temp = temp.next;
    }
    return count;
}

双向链表的实现

定义双向链表节点类

定义双向链表的节点类Node,由data和两个指针pre和next三部分组成,即数据、前一个节点和后一个节点的指针。

class DNode {
    int data;
    DNode pre;
    DNode next;

    public DNode(int data) {
        this.data = data;
        this.pre = null;
        this.next = null;
    }
}

双向链表的基本操作

双向链表的基本操作,类似于单向链表,包括增加节点、删除节点和遍历节点等。

增加节点

在链表末尾添加一个节点,并使新节点成为新的末尾节点。

public void addNode(int data) {
    DNode newNode = new DNode(data);
    if (head == null) {    // 添加的节点为头节点
        head = newNode;
        return;
    }
    DNode temp = head;
    while (temp.next != null) {
        temp = temp.next;
    }
    temp.next = newNode;
    newNode.pre = temp;
}

删除节点

删除链表中指定节点,需要找到该节点的前一个节点和后一个节点,使得它们的指针相互指向。

public void deleteNode(int data) {
    if (head == null) {    // 空链表
        return;
    }
    if (head.data == data) {   // 删除头节点
        head = head.next;
        head.pre = null;
        return;
    }
    DNode temp = head;
    while (temp.next != null && temp.next.data != data) {
        temp = temp.next;
    }
    if (temp.next == null) {  // 节点不存在
        return;
    }
    temp.next = temp.next.next;
    if (temp.next != null) {
        temp.next.pre = temp;
    }
}

遍历节点

遍历链表中的所有节点。

public void traverse() {
    DNode temp = head;
    while (temp != null) {
        System.out.print(temp.data + "<->");
        temp = temp.next;
    }
    System.out.println("null");
}

链表的反转

对于链表反转,常见的方法有递归和迭代两种方法。

递归反转单向链表

public Node reverse(Node node) {
    if (node == null || node.next == null) {
        return node;
    }
    Node newHead = reverse(node.next);
    node.next.next = node;
    node.next = null;
    return newHead;
}

迭代反转单向链表

public Node reverse(Node head) {
    Node prev = null;
    Node curr = head;
    while (curr != null) {
        Node nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

非递归反转双向链表

public void reverse() {
    DNode pre = null;
    DNode curr = head;
    while (curr != null) {
        DNode nextTemp = curr.next;
        curr.next = pre;
        curr.pre = nextTemp;
        pre = curr;
        curr = nextTemp;
    }
    head = pre;
}

示例

示例1:单向链表的基本操作

public class Main {
    public static void main(String[] args) {
        LinkList linkList = new LinkList();
        linkList.addNode(10);
        linkList.addNode(20);
        linkList.addNode(30);
        linkList.addNode(40);

        linkList.traverse();        // 10->20->30->40->null

        linkList.deleteNode(20);
        linkList.deleteNode(40);

        linkList.traverse();        // 10->30->null

        int length = linkList.length();
        System.out.println("length=" + length);    // length=2
    }
}

示例2:双向链表的基本操作和反转操作

public class Main {
    public static void main(String[] args) {
        DLinkList dLinkList = new DLinkList();
        dLinkList.addNode(10);
        dLinkList.addNode(20);
        dLinkList.addNode(30);
        dLinkList.addNode(40);

        dLinkList.traverse();       // 10<->20<->30<->40<->null

        dLinkList.deleteNode(20);
        dLinkList.deleteNode(40);

        dLinkList.traverse();       // 10<->30<->null

        dLinkList.reverse();
        dLinkList.traverse();       // 30<->10<->null
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之链表实现(单向、双向链表及链表反转) - Python技术站

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

相关文章

  • Android开发数据结构算法ArrayList源码详解

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

    数据结构 2023年5月17日
    00
  • 设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码。若接收方收到的数据信息x’ =1101,说明如何定位错误并纠正错误

    题目:设要采用CRC编码传送的数据信息x=1001,当生成多项式为G(x)=1101时,请写出它的循环校验码。若接收方收到的数据信息x’ =1101,说明如何定位错误并纠正错误 根据题目描述,需要采用CRC编码对数据信息x=1001进行编码,生成多项式为G(x)=1101。下面是计算循环冗余校验码的步骤:1.首先将数据信息x乘以x的次数,使得它的位数与G(x…

    算法与数据结构 2023年4月18日
    00
  • Java 中很好用的数据结构(你绝对没用过)

    Java 中很好用的数据结构(你绝对没用过) 介绍 Java 中的数据结构有很多,比如数组、链表、栈、队列、堆、树等等。在这些常见的数据结构中,我们或多或少都会使用到。但是本篇文章要讲述的是一些比较冷门,但是很好用的数据结构。 双向队列(Deque) 双向队列,顾名思义,是一种可以双向操作的队列。它可以从队列的两端插入和删除元素,因此常被用作实现栈和队列以及…

    数据结构 2023年5月17日
    00
  • C++二叉树结构的建立与基本操作

    C++二叉树是一种非常常见的数据结构,同时也是算法中经常使用的一种数据结构。本文将详细讲解C++二叉树的建立和基本操作,包括二叉树的定义、创建、遍历和删除等。 1. 二叉树的定义 二叉树是一种树形结构,每个节点最多只有两个子节点:左子节点和右子节点。树的深度取决于有多少个节点,根节点是最顶端的节点,不再有父节点。节点之间存在一些有天然排序关系且有先后性的关系…

    数据结构 2023年5月17日
    00
  • redis数据结构之intset的实例详解

    Redis数据结构之intset的实例详解 介绍 Redis是一个高性能的key-value存储系统,支持多种数据结构。其中,intset是Redis内置的一种特殊的数据结构,它可以高效地存储整型数据。 本篇文章将介绍intset的基本特性、底层实现以及相关用例,以便读者能够更好地了解该数据结构在Redis中的应用。 intset的基本特性 intset是一…

    数据结构 2023年5月17日
    00
  • C++高级数据结构之线段树

    C++高级数据结构之线段树攻略 什么是线段树 线段树是一种数据结构,它可以支持区间查询和单点修改,是处理静态区间问题的常用手段。它利用了 二分思想,将区间离散化成一些个体,然后考虑对个体进行处理,再结合区间合并的特性,更新区间信息。线段树主要由四个操作构成:建树、单点修改、区间查询和区间修改。 线段树的数据表示 在实现线段树时,我们需要考虑数据结构的几个要素…

    数据结构 2023年5月17日
    00
  • C语言编程数据结构的栈和队列

    C语言编程数据结构的栈和队列 什么是栈 栈(Stack) 是限定仅在表尾进行插入和删除操作的线性表。栈也称为后进先出( Last In First Out)的线性表,简称 LIFO 结构。栈结构有两个最重要的操作:入栈和出栈。其中,入栈操作向栈中添加一个元素,出栈操作从栈中删除一个元素。 栈的基本操作 初始化栈 入栈 出栈 取栈顶元素 判空 判满 // 栈的…

    数据结构 2023年5月17日
    00
  • C语言 超详细讲解算法的时间复杂度和空间复杂度

    C语言 超详细讲解算法的时间复杂度和空间复杂度 什么是时间复杂度和空间复杂度? 在进行算法分析时,我们需要考虑的两个重要因素是时间复杂度和空间复杂度。时间复杂度是指算法所需要的时间量,而空间复杂度是指算法所需要的空间量。在编写算法时,我们常常需要考虑如何在时间和空间两者之间做出平衡,以使算法既有足够高的效率,又不占用过多的资源。 如何计算时间复杂度? 计算时…

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