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日

相关文章

  • 【ACM数论】和式变换技术,也许是最好的讲解之一

    在做数论题时,往往需要进行和式变换,然后变换成我们可以处理的和式,再针对和式做筛法、整除分块等操作。 本文将介绍一些常见的和式变换技术。 以下出现的概念大部分为个人总结,未必是学术界/竞赛界的统一说法,有不严谨的地方请谅解。 ? 作者:Eriktse? 简介:19岁,211计算机在读,现役ACM银牌选手?力争以通俗易懂的方式讲解算法!❤️欢迎关注我,一起交流…

    算法与数据结构 2023年4月17日
    00
  • Python数据结构之Array用法实例

    Python数据结构之Array用法实例 在Python中,Array是一种很有用的数据结构类型。它可以通过简单的方式存储一系列数据,提供快速的索引访问和高效的操作。本文将详细探讨Python中Array的用法,包括创建Array、插入、删除、修改、查找和遍历等。 创建Array 要创建一个Array,需要使用array模块。在调用前,需要首先导入该模块。A…

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

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

    算法与数据结构 2023年4月17日
    00
  • 带你了解Java数据结构和算法之队列

    带你了解Java数据结构和算法之队列 一、介绍 队列是已知的最古老和最常用的数据结构之一。它是一个线性结构,它遵循一个先进先出的原则,在日常生活中我们也很容易碰到队列。比如:在银行排队办理业务、队列中的电影厅、厨房中的菜单等等。 队列的操作主要有两种:入队(enqueue)和出队(dequeue)。插入操作只能在队尾进行,删除操作只能在队头进行。还有一些常用…

    数据结构 2023年5月17日
    00
  • F – 产生冠军(不使用拓扑排序)

    题目描述 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。球赛的规则如下:如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之…

    算法与数据结构 2023年4月17日
    00
  • C语言深入浅出讲解顺序表的实现

    C语言深入浅出讲解顺序表的实现 顺序表简介 顺序表是一种线性表的存储结构,它是由连续的内存空间来存储线性表中的元素。 顺序表的特点是支持查找、插入和删除操作,操作效率较高,但需要提前分配足够大的内存空间。当顺序表空间不足时,需要扩容,移动数据较为麻烦。 顺序表的实现 数据结构定义 顺序表的数据结构定义包含以下几个成员: 数据元素数组 data,存储线性表中的…

    数据结构 2023年5月17日
    00
  • C++数据结构关于栈迷宫求解示例

    C++数据结构关于栈迷宫求解示例攻略 在本篇攻略中,我们将使用C++数据结构中的栈来解决迷宫问题,具体将通过两个示例来详细讲解该方法。首先介绍一下栈的概念。 栈的概念 栈是一种“后入先出”的数据结构,即最后压入栈中的元素会首先被弹出,而最早压入栈中的元素会最后被弹出。栈的基本操作有入栈(push)、出栈(pop)、判断是否为空以及读取栈顶元素等。 迷宫问题 …

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

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

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