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日

相关文章

  • C语言深入讲解链表的使用

    C语言深入讲解链表的使用 什么是链表? 链表是一种常用的数据结构,它的存储方式是通过指针相互连接实现的。链表是由若干个节点(node)构成的,每个节点都存储着一些信息和指向下一个节点的指针。 链表实现的基本操作 链表的基本操作包括插入节点、删除节点以及遍历链表。我们下面将通过代码示例详细介绍这些操作。 插入节点 链表的插入节点操作是指在链表的某一位置插入一个…

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

    A. TubeTube Feed 分析: 从所有a[i]+i-1<=t的选择种取个max即可 code: #include <bits/stdc++.h> using namespace std; const int N = 55; int a[N], b[N]; int main() { std::ios::sync_with_stdio…

    算法与数据结构 2023年5月4日
    00
  • Javascript中扁平化数据结构与JSON树形结构转换详解

    一、扁平化数据结构 扁平化数据结构是指将一个JSON树形结构数据转换为一个扁平化的对象数组,通常用于在数据操作中进行遍历和检索,方便数据的处理和展示。 例如,有一个JSON树形结构数据如下: { "name": "中国", "children": [ { "name": &quo…

    数据结构 2023年5月17日
    00
  • C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解

    C语言数据结构顺序表中的增删改(尾插尾删)教程示例详解 什么是顺序表 顺序表是一种线性表,它通过一块连续的存储空间来存储数据。顺序表中的数据元素排列在物理存储空间上也是连续的,每个元素占用一个固定的位置和大小,并且使用下标来访问。 顺序表的定义 下面是以int类型为例的一个简单顺序表的定义: #define SIZE 50 typedef struct { …

    数据结构 2023年5月17日
    00
  • C语言数据结构之 折半查找实例详解

    C语言数据结构之 折半查找实例详解 什么是折半查找? 折半查找是一种在有序数组中查找某个特定元素的算法。其基本思想是将查找的值与数组的中间元素比较,如果比中间元素小,则在数组的左半部分查找;如果比中间元素大,则在数组的右半部分查找,直到找到该元素或查找范围为空。 折半查找算法的流程 确定要查找的数组arr和其元素个数n,以及要查找的元素value。 设定左边…

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

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

    算法与数据结构 2023年4月17日
    00
  • 莫比乌斯反演,欧拉反演学习笔记

    (未更完) 我算法中也就差点数论没学了,这几周卷了,学了一下,分享一下啊。 我会讲得详细一点,关于我不懂得地方,让新手更容易理解。 学习反演有很多定义啥的必须要记的,学的时候容易崩溃,所以希望大家能坚持下来。   第一个定义: $\lfloor x\rfloor$:意思是小于等于 $x$ 的最大整数。 数论分块 学习反演之前,要先学习一些边角料,先来看数论分…

    算法与数据结构 2023年4月17日
    00
  • 二叉搜索树的本质

    引言 打算写写树形数据结构:二叉查找树、红黑树、跳表和 B 树。这些数据结构都是为了解决同一个基本问题:如何快速地对一个大集合执行增删改查。 本篇是第一篇,讲讲搜索树的基础:二叉搜索树。 基本问题 如何在一千万个手机号中快速找到 13012345432 这个号(以及相关联信息,如号主姓名)? 最笨的方案 把一千万个手机号从头到尾遍历一遍,直到找到该手机号,返…

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