带头节点的单链表的思路及代码实现

带头节点的单链表的思路及代码实现(JAVA)

一、什么是的单链表

①标准定义

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) +指针(指示后继元素存储位置,元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。)

以上是标准定义不太好让人对单链表有直观的感受,下面我们通过对单链表的构成以及存储数据的方式说明,来更加深刻的理解一下什么是单链表。

②个人理解

链表存储数据的方式:

  1. 链表是以节点的方式来存储数据的

    • 那么节点又是什么呢?节点就是链表要存储的每个数据块,只不过这个数据块中不仅包含我们要存储的data,同时又多了一个next用来指向下一个数据节点所在的位置。
  2. 每个数据节点包含data域,next域:指向下一个数据节点

  3. 链表的各个节点在实际存储结构上不一定是连续的

    • 链表就是在添加数据时不去考虑数据所要添加的实际物理位置,只需要通过next域来确定数据节点的逻辑线性结构即可;
  4. 列表分带头节点的链表和不带头节点的链表,根据实际需求来确定使用哪种链表(本文以单链表进行举例说明)

    • 那么头节点的作用又是什么呢?其实头节点中有效域只有next域,用来指向链表中第一个节点所在的位置。

链表的实际结构图示:

image-20230326104918229链表的逻辑结构图示:

image-20230326105842499

二、代码实现

①定义数据节点类

// 定义数据节点类
class DataNode {

    private String data;    // data域,要存储的数据
    private DataNode next;  // next域,用于指向下一个数据节点地址

    // 数据节点构造器
    public DataNode(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "DataNode{" +
                "data='" + data + '\'' +
                '}';
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public DataNode getNext() {
        return next;
    }

    public void setNext(DataNode next) {
        this.next = next;
    }
    
}

②定义单链表类

/**
 * ClassName: SingleLinkedList
 * Package: com.zhao.test
 * Description: 定义单向链表类
 *
 * @Author XH-zhao
 * @Create 2023/3/26 11:09
 * @Version 1.0
 */
public class SingleLinkedList {

    // 先初始化一个头节点,头节点不用于存储数据,只用于指向单链表的首元素
    private DataNode head = new DataNode("");

    /**
     * 向单链表中增加数据节点
     *
     * @param dataNode 待增加的数据节点
     */
    public void addDataNode(DataNode dataNode) {

        // 由于head节点不能更改,只用于指向单链表的首元素,所以我们需要一个辅助变量接收head的引用
        DataNode temp = head;

        // 找到链表的最后,即结束
        while (temp.getNext() != null) {
            // 如果没有找到,就把下一个数据节点的引用赋值给temp,使temp指向下一个数据节点
            temp = temp.getNext();
        }

        // 将找到的最后一个一个数据节点的next域指向新加入的节点地址
        temp.setNext(dataNode);

    }

    /**
     * 显示链表的信息
     */
    public void showList() {
        // 判断链表是否为空
        if (head.getNext() == null){
            System.out.println("链表为空");
            return;
        }

        // 由于head节点不能更改,只用于指向单链表的首元素,所以我们需要一个辅助变量接收head的引用
        DataNode temp = head.getNext();

        // 遍历链表并打印链表中的数据节点
        while (temp != null) {
            System.out.println(temp);
            temp = temp.getNext();
        }

    }

}

三、实验测试单链表的代码准确性

①单链表实现以及测试的整体代码

/**
 * ClassName: SingleLinkedList
 * Package: com.zhao.test
 * Description: 定义单向链表类
 *
 * @Author XH-zhao
 * @Create 2023/3/26 11:09
 * @Version 1.0
 */
public class SingleLinkedList {

    // 先初始化一个头节点,头节点不用于存储数据,只用于指向单链表的首元素
    private DataNode head = new DataNode("");

    /**
     * 向单链表中增加数据节点
     *
     * @param dataNode 待增加的数据节点
     */
    public void addDataNode(DataNode dataNode) {

        // 由于head节点不能更改,只用于指向单链表的首元素,所以我们需要一个辅助变量接收head的引用
        DataNode temp = head;

        // 找到链表的最后,即结束
        while (temp.getNext() != null) {
            // 如果没有找到,就把下一个数据节点的引用赋值给temp,使temp指向下一个数据节点
            temp = temp.getNext();
        }

        // 将找到的最后一个一个数据节点的next域指向新加入的节点地址
        temp.setNext(dataNode);

    }

    /**
     * 显示链表的信息
     */
    public void showList() {
        // 判断链表是否为空
        if (head.getNext() == null){
            System.out.println("链表为空");
            return;
        }

        // 由于head节点不能更改,只用于指向单链表的首元素,所以我们需要一个辅助变量接收head的引用
        DataNode temp = head.getNext();

        // 遍历链表并打印链表中的数据节点
        while (temp != null) {
            System.out.println(temp);
            temp = temp.getNext();
        }

    }

}

// 定义数据节点类
class DataNode {

    private String data;    // data域,要存储的数据
    private DataNode next;  // next域,用于指向下一个数据节点地址

    // 数据节点构造器
    public DataNode(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "DataNode{" +
                "data='" + data + '\'' +
                '}';
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public DataNode getNext() {
        return next;
    }

    public void setNext(DataNode next) {
        this.next = next;
    }

}

// 单链表测试类
class SingleLinkedListTest{

    public static void main(String[] args) {

        // 创建四个数据节点
        DataNode dataNode1 = new DataNode("data1");
        DataNode dataNode2 = new DataNode("data2");
        DataNode dataNode3 = new DataNode("data3");
        DataNode dataNode4 = new DataNode("data4");

        // 创建单链表对象
        SingleLinkedList linkedList1 = new SingleLinkedList();

        // 将数据节点依次加入链表中
        linkedList1.addDataNode(dataNode1);
        linkedList1.addDataNode(dataNode2);
        linkedList1.addDataNode(dataNode3);
        linkedList1.addDataNode(dataNode4);

        // 展示链表内所有数据节点
        linkedList1.showList();
    }

}

②实验结果

DataNode{data='data1'}
DataNode{data='data2'}
DataNode{data='data3'}
DataNode{data='data4'}

进程已结束,退出代码0

从上述结果中,我们就实现了带头节点的单链表的数据存储设计。

四、实验总结

在上述的实验测试中我们已经完成了单链表存储数据的基本思想。可以让数据节点根据添加顺序依次添加到单链表当中。到这里我们仅仅实现了如何使用单链表的方式存储数据元素。那么如果我们想让数据节点在存储时,实现一些我们想要的特殊功能(例如在添加数据节点的同时,按照数据节点中的某一个属性进行排序加入),我们又该如何实现呢?

这里我们更改一下我们的测试程序,我们将数据节点以4-1-2-3顺序加入链表中,希望呈现出来还是以1-2-3-4排序好的效果。

public static void main(String[] args) {

    // 创建四个数据节点
    DataNode dataNode1 = new DataNode("data1");
    DataNode dataNode2 = new DataNode("data2");
    DataNode dataNode3 = new DataNode("data3");
    DataNode dataNode4 = new DataNode("data4");

    // 创建单链表对象
    SingleLinkedList linkedList1 = new SingleLinkedList();

    // 将数据节点以4-1-2-3顺序加入链表中
    linkedList1.addDataNode(dataNode4);
    linkedList1.addDataNode(dataNode1);
    linkedList1.addDataNode(dataNode2);
    linkedList1.addDataNode(dataNode3);

    // 展示链表内所有数据节点
    linkedList1.showList();
}
DataNode{data='data4'}
DataNode{data='data1'}
DataNode{data='data2'}
DataNode{data='data3'}

进程已结束,退出代码0

很显然,我们的代码只能按照节点加入顺序来加入节点。后续我们将在《JAVA实现节点加入到单链表时按需求排序》一文中实现上述我们想要的效果!

番外:重复增添数据节点到新链表时BUG思考

如果上述实验中我们按照如下方式去测试代码

public static void main(String[] args) {

    // 创建四个数据节点
    DataNode dataNode1 = new DataNode("data1");
    DataNode dataNode2 = new DataNode("data2");
    DataNode dataNode3 = new DataNode("data3");
    DataNode dataNode4 = new DataNode("data4");

    // 创建单链表对象
    SingleLinkedList linkedList1 = new SingleLinkedList();

    // 将数据节点依次加入链表中
    linkedList1.addDataNode(dataNode1);
    linkedList1.addDataNode(dataNode2);
    linkedList1.addDataNode(dataNode3);
    linkedList1.addDataNode(dataNode4);

    // 展示链表内所有数据节点
    linkedList1.showList();

    // 创建链表2
    SingleLinkedList linkedList2 = new SingleLinkedList();

    // 将数据节点打乱顺序加入到链表2中
    linkedList2.addDataNode(dataNode1);
    linkedList2.addDataNode(dataNode4);
    linkedList2.addDataNode(dataNode3);
    linkedList2.addDataNode(dataNode2);

    // 展示链表2内所有数据节点
    linkedList2.showList();
}

运行结果:

DataNode{data='data1'}
DataNode{data='data2'}
DataNode{data='data3'}
DataNode{data='data4'}
// 程序堵塞在这里,无法向下进行!

请思考造成上述问题的原因所在?

原文链接:https://www.cnblogs.com/zhao-XH/p/17298428.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:带头节点的单链表的思路及代码实现 - Python技术站

(2)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • python广度搜索解决八数码难题

    下面是关于“Python广度搜索解决八数码难题”的完整攻略。 1. 什么是八数码难题 八数码难题是一种经典的数学难题,它的目标是将一个3×3的方格中的数字从初始状态移动到目标状态。在移动过程中,每次只能将一个数字移动到空格中,最终达到目标状态。 2. 广度搜索算法 广度搜索算法是一种常用的搜索算法它的目标是从起始状态开始,逐步扩展搜索空间,直到找到目标状态。…

    python 2023年5月13日
    00
  • 剑指 Offer 33. 二叉搜索树的后序遍历序列(java解题)

    目录 1. 题目 2. 解题思路 3. 数据类型功能函数总结 4. java代码 5. 踩坑小记 递归调用,显示StackOverflowError 1. 题目 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树: 5 / \ 2 6 /…

    算法与数据结构 2023年4月23日
    00
  • PHP 数据结构 算法 三元组 Triplet

    PHP 数据结构 算法 三元组 Triplet 什么是三元组 Triplet 三元组 Triplet 是指由三个数据分别确定一个元素的数据类型。 在 PHP 中可以用一个数组来实现三元组,数组下标表示元素的序号,数组中储存的则是元素的值,共有三个元素。 例如一个三元组 (a, b, c),可以用 PHP 数组表示为 $triplet = array(a, b…

    数据结构 2023年5月17日
    00
  • rsa详解及例题及python算法

    下面是详细讲解“RSA算法详解及例题及Python算法”的完整攻略,包含两个示例说明。 RSA算法简介 RSA算法是一种非对称加密算法,的基本原理是利用两个大质数的乘积作为公钥,而这两个质数的乘积作为私钥。RSA算的优点是安全高,但是加解速度较慢。 RSA算法的实现 下是RSA算法的实现过程: 1. 两个大质数p和q 这两个质数的乘积n=p*q,n的长度就是…

    python 2023年5月14日
    00
  • Python实现的数据结构与算法之基本搜索详解

    Python实现的数据结构与算法之基本搜索详解 在计算机科学中,搜索指的是在一组数据中找到目标数据的过程。搜索算法是解决各种问题的关键,即使是拼图游戏和图像识别也要依赖搜索算法。本文将介绍基本的搜索算法,包括线性/顺序搜索、二分搜索和广度优先搜索。 线性/顺序搜索 顺序搜索又称为线性搜索,它遍历整个数据集以查找特定元素。顺序搜索可以用于查找未排序的列表。该算…

    数据结构 2023年5月17日
    00
  • 「学习笔记」数位 DP

    「学习笔记」数位 DP 意义不大的题不写了。 点击查看目录 目录 「学习笔记」数位 DP 概述 例题 P2657 [SCOI2009] windy 数 思路 代码 P4317 花神的数论题 思路 P4124 [CQOI2016]手机号码 思路 代码 haha数 题意 思路 代码 0和1的熟练 题意 思路 代码 苍与红的试炼 题意 思路 代码 概述 数位 DP…

    算法与数据结构 2023年4月17日
    00
  • 使用python实现递归版汉诺塔示例(汉诺塔递归算法)

    下面是详细讲解“使用Python实现递归版汉诺塔示例(汉诺塔递归算法)”的完整攻略。 汉诺塔问题 汉诺塔问题是一个经典的递归问题,其问题描述如下: 有三个柱子A、B、C,A柱子上有n个盘子,盘子大小不等,大的在下,小的在上。现在要将A柱子上的盘子移动到C柱子上,移动过程中可以借助B柱子,但要求任何时刻都不能出现大盘子小盘子上方的情况。问如何移动才能完成任务?…

    python 2023年5月14日
    00
  • 使用Python求解最大公约数的实现方法

    使用Python求解最大公约数的实现方法 什么是最大公约数? 最大公约数(Greatest Common Divisor,简称GCD)是指两个或多个整数共有约数最大的一个。例如,12和18的最大公约数是6。 Python求解最大公约数的实现 Python求解最大公约数的实现方法有多种,下面介绍两种常用的方法。 方法一:辗转相除法 辗转相除法,也称欧几里得算法…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部