数据结构与算法(三):单向链表

这篇具有很好参考价值的文章主要介绍了数据结构与算法(三):单向链表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

链表定义

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑是通过链表种的指针链接次序实现的。链表由一系列节点组成,每个节点包括两部分:一个是存储数据元素的数据域,一个是存储下一个节点地址的指针域。单向链表从头节点(也可以没有头节点)开始,指针指向下一个节点的位置,只能由上一个节点指向后面节点,后面节点不能指向前面节点。单向链表示意图
数据结构与算法(三):单向链表

节点结构

节点包含了数据域和指针域。数据域存放该节点存放的数据信息,指针域存放下一个节点的存储地址。no、nickName、name为该节点的数据内容,nextNode为下一个节点。

public class Node {
    private Integer no;
    private String name;
    private String nickName;
    private Node nextNode;
    public Node(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }
    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}

链表操作

初始化单向链表

初始化链表的头节点,头节点数据域为空,指针域为下一个节点的位置。

private Node head = new Node(0, "", "");

遍历链表

因为单向链表的头节点不能移动,所以借助一个临时节点变量进行遍历。

public void showLinkList() {
    if (head.getNextNode() == null) {
        System.out.println("链表为空");
        return;
    }
    Node temp = head.getNextNode();
    while (true) {
        if (temp == null) {
            break;
        }
        System.out.println(temp);
        temp = temp.getNextNode();
    }
}

插入元素

该方法只是将新的节点放到节点的末尾去,并不考虑顺序等因素。

public void addNode(Node node) {
   // 因为head是不能动的,所以需要借助一个临时变量
   Node temp = head;
   while (true) {
       if (temp.getNextNode() == null) {
           break;
       }
       temp = temp.getNextNode();
   }
   temp.setNextNode(node);
}

该方法将新的节点放到节点中去,考虑节点的顺序(以节点的 no 属性为顺序)。

public void addSortNode(Node node) {
    Node temp = head;
    boolean isExist = false;
    while (true) {
        if (temp.getNextNode() == null) {
            break;
        }
        // 对应的序号已经存在
        if (temp.getNo().equals(node.getNo())) {
            isExist = true;
            break;
        }
        if (temp.getNextNode().getNo() > node.getNo()) {
            break;
        }
        temp = temp.getNextNode();
    }
    if (isExist) {
        System.out.println("插入的序号 " + node.getNo() + " 已存在");
    } else {
        node.setNextNode(temp.getNextNode());
        temp.setNextNode(node);
    }
}

更新节点

更新某一个节点的数据域内容

public void updateNode(Node node) {
    if (head.getName().equals("")) {
        System.out.println("链表为空");
    }
    Node temp = head.getNextNode();
    while (true) {
        if (temp == null) {
            break;
        }
        if (temp.getNo() == node.getNo()) {
            break;
        }
        temp = temp.getNextNode();
    }
    if (temp == null || temp.getNo() != node.getNo()) {
        System.out.println("没有找到对应的节点");
    } else {
        temp.setName(node.getName());
        temp.setNickName(node.getNickName());
    }
}

删除节点

找到要删除节点的上一个节点,将该节点的指针域设置成要删除节点的下一个节点,这样要删除的节点就没有指针指向了,就会被GC回收,达到删除节点的目的。

public void deleteNode(Integer no) {
    if (head.getNextNode() == null) {
        System.out.println("链表为空");
    }
    Node temp = head;
    while (true) {
        if (temp.getNextNode() == null) {
            break;
        }
        if (temp.getNextNode().getNo() == no) {
            break;
        }
        temp = temp.getNextNode();
    }
    if (temp.getNextNode() == null) {
        System.out.println("未找到节点");
        return;
    }
    temp.setNextNode(temp.getNextNode().getNextNode());
}

有效节点的个数

public Integer getListNodeConunt() {
    if (head.getNextNode() == null) {
        return 0;
    }
    Node temp = head.getNextNode();
    Integer count = 0;
    while (true) {
        if (temp == null) {
            break;
        }
        count++;
        temp = temp.getNextNode();
    }
    return count;
}

倒数{}个节点

因为单向链表的后一个节点是无法获取到前一个节点的位置的,所以我们先计算出该链表的有效节点个数,再用有效节点个数 - 倒数的节点个数就是正数的节点个数,这样可以达到同样的效果。

public Node getLastNode(SingleLinkList list, Integer index) {
    Integer count = list.getListNodeConunt();
    if (Optional.of(list).isEmpty()) {
        return null;
    }
    // 第几个元素
    Integer indexPosition = 0;
    Node temp = head.getNextNode();
    while (true) {
        if (temp == null) {
            break;
        }
        // 因为链表是单向的,只能从前往后找,倒数第几个=总数-倒数的数
        if (indexPosition == (count - index)) {
            return temp;
        }
        indexPosition++;
        temp = temp.getNextNode();
    }
    return null;
}

链表反转

遍历旧链表,第一个节点放入新链表的第一个节点,第二个节点的下一个节点设置成新链表的第一个节点,以此类推,旧链表的第一个就成了新链表的最后一个节点,第二个节点就成了新链表的倒数第二个节点...

public void getReverseList(Node head) {
    // 如果当前链表为空,或者只有一个节点,无需反转,直接返回
    if (head.getNextNode() == null || head.getNextNode().getNextNode() == null) {
        return;
    }
    // 定义一个辅助变量,帮助遍历原来的链表
    Node cur = head.getNextNode();
    // 指向当前节点cur的下一个节点
    Node next = null;
    Node reverseHead = new Node(0, "", "");
    // 遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead的最前端
    while (cur != null) {
        // 先暂时保存当前节点的下一个节点,因为后面需要使用
        next = cur.getNextNode();
        // 将cur的下一个节点指向新的链表的最前端
        cur.setNextNode(reverseHead.getNextNode());
        reverseHead.setNextNode(cur);
        // 让cur后移
        cur = next;
    }
    // 将head.next 指向reverseHead.next,实现单链表的反转
    head.setNextNode(reverseHead.getNextNode());
}

逆序打印

利用栈结构先进后出的特点,将遍历的链表节点依次入栈,再打印栈中的节点,这样可以在不改变原来链表数据的情况下进行逆序打印输出。文章来源地址https://www.toymoban.com/news/detail-618693.html

public void reversePrint(Node head) {
    if (head.getNextNode() == null) {
        return;
    }
    // 创建一个栈,将各个节点压入栈
    Stack<Node> stack = new Stack<>();
    Node cur = head.getNextNode();
    while (cur != null) {
        stack.push(cur);
        cur = cur.getNextNode();
    }
    while (stack.size() > 0) {
        System.out.println(stack.pop());
    }
}

到了这里,关于数据结构与算法(三):单向链表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】动图详解单向链表

    目录 1.什么是链表         1.问题引入         2. 链表的概念及结构         3. 问题解决 2.单向链表接口的实现         1.接口1,2---头插,尾插         2. 接口3,4---头删,尾删         3. 接口5---查找          4. 接口6,7---插入,删除         5. 接口

    2024年01月18日
    浏览(25)
  • 【数据结构篇】手写双向链表、单向链表(超详细)

    什么是链表 ? 链表(Linked List)是用链式存储结构实现的线性表。链表示意图: 链表的组成 : 数据域 + 引用域 (数据域和引用域合称结点或元素) 数据域存放数据元素自身的数据 引用域存放相邻结点的地址 链表的特点 : 链表中元素的联系依靠引用域 具有线性结构的特

    2024年02月11日
    浏览(15)
  • 数据结构:线性表之-单向链表(无头)

    目录 什么是单向链表 顺序表和链表的区别和联系 顺序表: 链表: 链表表示(单项)和实现 1.1 链表的概念及结构 1.2单链表(无头)的实现 所用文件 将有以下功能: 链表定义 创建新链表元素 尾插 头插 尾删 头删 查找-给一个节点的指针 改 pos位置之前插入 删除pos位置的值 成品

    2024年02月09日
    浏览(17)
  • 数据结构——单向链表(C语言版)

    在数据结构和算法中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在C语言中,我们可以使用指针来实现单向链表。下面将详细介绍如何用C语言实现单向链表。 目录 1. 定义节点结构体 2. 初始化链表 3. 插入节点 4. 删除节点

    2024年03月24日
    浏览(16)
  • 【数据结构】单向链表实现 超详细

    目录 一. 单链表的实现 1.准备工作及其注意事项 1.1 先创建三个文件 1.2 注意事项:帮助高效记忆和理解 2.链表的基本功能接口 2.0 创建一个 链表 2.1 链表的 打印  3.链表的创建新节点接口 4.链表的节点 插入 功能接口 4.1 尾插接口 4.2 头插接口     4.3 指定位置 pos 之前  插入

    2024年02月19日
    浏览(27)
  • 数据结构《链表》无头单向非循环-动图详解

    前面学习了顺序表发现,顺序表虽然好,但也有很多不足的地方,比方说,顺序表是一块连续的物理空间,如果头插或者头删,那么整个数组的数据都要移动。但是链表不一样,链表是通过指针访问或者调整,链表是物理空间是不连续的,通过当前的next指针找到下一个。 插

    2024年02月06日
    浏览(19)
  • 数据结构day06(单向循环链表、双向链表)

    双向链表的练习代码 head.h fun.c main.c 今日思维导图哈 ​​​​​​​

    2024年02月10日
    浏览(13)
  • 第14章_集合与数据结构拓展练习(前序、中序、后序遍历,线性结构,单向链表构建,单向链表及其反转,字符串压缩)

    1、前序、中序、后序遍历 分析: 完全二叉树: 叶结点只能出现在最底层的两层,且最底层叶结点均处于次底层叶结点的左侧 2、线性结构 3、其它 4、单向链表构建 (1)定义一个单向链表SingleLinked类 包含私有的静态内部类Node 包含Object类型的data属性和Node类型的next属性 包含

    2024年01月23日
    浏览(19)
  • 【数据结构】之十分好用的“链表”赶紧学起来!(第一部分单向链表)

    💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃 个人主页 :阿然成长日记 👈点击可跳转 📆 个人专栏: 🔹数据结构与算法🔹C语言进阶 🚩 不能则学,不知则问,耻于问人,决无长进 🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍 前言 🎸小伙伴们,

    2024年02月14日
    浏览(20)
  • 【数据结构C/C++】单向链表的增删改查

    单向链表是比较常用的数据结构,最近再面试手撕算法的时候偶尔有遇到,所以就花了一点时间简单的写了一下C/C++版本的单向链表的代码。 这里我推荐使用C++版本,因为C++版本我特地优化了一下,提供了用户输入的功能,当然两个语言差异不大,注释可以直接看C版本的,比

    2024年02月07日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包