文章目录

  • 1 单向链表反转
  • 2 快慢指针
    • 2.1 中间值问题
    • 2.2 单向链表是否有环
    • 2.3 有环链表入口
  • 3 后记

1 单向链表反转

  • 需求:原链表数据1->2->3->4,反转之后链表中的数据4->3->2->1。效果图示,

  • 思路:

    1. 非递归:从第一个节点开始遍历链表,记录前一个节点,当前节点,后一个节点;把当前节点的next指针指向前一个节点,指针后移,直到链表结尾,交换头指针和尾指针,整个链表反转完成。

      • 指针后移指当前节点指针赋值给前一个节点指针,后一个指针节点赋值给当前节点,后一个节点指针.next赋值给后一个节点指针
    2. 递归实现:从第一个节点开始,依次递归调用反转每一个节点直到最后一个节点既原尾节点现在的头结点,整个链表反转完成。
  • 思路2递归实现

    • API:把下面2个方法放入我们前面实现的单向链表中

      • public void reverse():反转整个链表
      • public Node reverse(Noce curr):反转当前节点
    • 代码:

      /*** 反转单向链表*/
      public void reverse() {if (size == 0 || size == 1) {return;}// 递归反转reverseRecursion(first);// 交换头尾指针Node<E> n = first;first = last;last = n;
      }private Node<E> reverseRecursion(Node<E> curr) {if (curr.next == null) {return curr;}Node<E> pre = reverseRecursion(curr.next);pre.next = curr;curr.next = null;return curr;
      }
      
    • 测试:

      ===反转前====
      [1, 2, 3, 4]
      ===反转后====
      [4, 3, 2, 1]
      
  • 非递归实现

    • 代码:

      /*** 单向链表反转非递归实现*/public void reverse() {if (size == 0 || size == 1) {return;}//Node<E> pre = null;Node<E> curr = first;Node<E> next = first.next;while (curr != null) {curr.next = pre;if (next == null) {break;}pre = curr;curr = next;next = next.next;}// 交换头尾指针Node<E> n = first;first = last;last = n;}
      
    • 测试:

      ===反转前====
      [1, 2, 3, 4]
      ===反转后====
      [4, 3, 2, 1]
      

2 快慢指针

快慢指针指的就是定义两个指针,这两个指针的移动速度一块一慢,快慢指针之间的差值可以让我们找到链表中的相应节点。一般情况下,快指针的移动步长为慢指针的两倍。

2.1 中间值问题

利用快慢指针查找链表中间节点。

原理:快慢指针初始位置为链表头,快指针移动步长2倍于慢指针,当快指针移动到链表末尾的时候,慢指针刚好移动到链表中间位置。

链表有7个节点,分别存储字符串aa,bb,cc,dd,ee,ff,gg,蓝色表示慢指针,每次移动一个节点位置;绿色表示快指针,每次移动2个节点位置,当绿色指针移动到链表结尾时,蓝色节点刚好移动到中间节点位置dd处。如图2.1-1所有:

用代码模拟实现,代码2.1-1如下:

public class FastSlowPointerTest {public static void main(String[] args) {// 创建链表Node<String> seven = new Node<>("gg", null);Node<String> six = new Node<>("ff", seven);Node<String> five = new Node<>("ee", six);Node<String> four = new Node<>("dd", five);Node<String> three = new Node<>("cc", four);Node<String> two = new Node<>("bb", three);Node<String> one = new Node<>("aa", two);// 获取中间节点的值System.out.println(getMid(one));}/*** 获取中间节点元素* @param first     头结点* @return          中间节点元素值*/public static String getMid(Node<String> first) {// 定义快慢指针Node<String> fast = first;Node<String> slow = first;while (fast != null && fast.next != null) {fast = fast.next.next;if (fast == null) {break;}slow = slow.next;}return slow.item;}/*** 节点类*/private static class Node<E> {E item;Node<E> next;public Node(E item, Node<E> next) {this.item = item;this.next = next;}}
}

2.2 单向链表是否有环

无环链表,前一节点指向后一节点,而后面节点不指向前面节点,如图2.2-1所示:

有环链表,前一节点指向后一节点,且后面节点指向前面节点,如图2.2-2所示:

快慢指针查找是否有环原理:快指针移动快,如有环路,当慢指针进入环路时,快指针已经在环路中,且快指针移动快,一直移动直至快慢指针相遇;如果没有环路,则快指针和慢指针不会相遇。

快慢指针查找环路图示2.2-3:

用代码模拟实现,代码2.2-1如下:

public class LinkListCircuitTest {public static void main(String[] args) {// 创建链表Node<String> seven = new Node<>("gg", null);Node<String> six = new Node<>("ff", seven);Node<String> five = new Node<>("ee", six);Node<String> four = new Node<>("dd", five);Node<String> three = new Node<>("cc", four);Node<String> two = new Node<>("bb", three);Node<String> one = new Node<>("aa", two);// 环路seven.next = three;// 判断链表是否有环路System.out.println(isCircuit(one));}/*** 判断链表是否有环路* @param first     头结点* @return          是否是环路*/public static boolean isCircuit(Node<String> first) {// 定义快慢指针Node<String> fast = first;Node<String> slow = first;while (fast != null && fast.next != null) {fast = fast.next.next;if (fast == null) {break;}slow = slow.next;if (fast == slow) {return true;}}return false;}/*** 节点类*/private static class Node<E> {E item;Node<E> next;public Node(E item, Node<E> next) {this.item = item;this.next = next;}}
}

2.3 有环链表入口

当检测的链表有环后,怎么找到入口呢?当快慢指针相遇时,这是重新设定一个新的指针指向链表的启点,且步长与慢指针一样为1,则慢指针与“新”指针相遇的地方就是环的入口。证明涉及数论的知识,本人还没有学,略过。

代码实现如下:

public static Node<String> getEntrance(Node<String> first) {// 定义快慢指针,临时指针Node<String> fast = first;Node<String> slow = first;Node<String> temp = null;// 遍历链表,先找的环(快慢指针相遇), 临时指针指向链表的启点,且步长与慢指针一样为1,则慢指针与临时指针相遇的地方就是环的入口while (fast != null && fast.next != null) {fast = fast.next.next;if (fast == null) {break;}slow = slow.next;if (fast == slow) {temp = first;continue;}if (temp != null) {temp = temp.next;if (temp == slow) {return slow;}}}return null;
}

测试代码同2.2一致

3 后记

​ 如果小伙伴什么问题或者指教,欢迎交流。

❓QQ:806797785

⭐️源代码仓库地址:https://gitee.com/gaogzhen/algorithm

参考:

[1]黑马程序员.黑马程序员Java数据结构与java算法全套教程,数据结构+算法教程全资料发布,包含154张java数据结构图[CP/OL].p56~p60.

应用-单向链表-数据结构和算法相关推荐

  1. python 判断div 之间的内容是否为空_python实现单向链表数据结构及其基本方法

    顺序表和链表作为线性表的典型结构,上一篇已经说了顺序表在python中的典型应用:list和tuple,<顺序表数据结构在python中的应用>,今天来实现链表的基本结构之一:单向链表. ...

  2. java集合单向链表_Java实现单向链表数据结构

    本文章同步到本人的博客站点 燕归来 链表是一种数据结构,和数组同级.比如,Java中我们使用的ArrayList,其实现原理是数组.而LinkedList的实现原理就是链表了.链表在进行循环遍历时效率 ...

  3. C++11中std::forward_list单向链表的使用

    std::forward_list是在C++11中引入的单向链表或叫正向列表.forward_list具有插入.删除表项速度快.消耗内存空间少的特点,但只能向前遍历.与其它序列容器(array.vec ...

  4. python数据结构与算法总结

    python常用的数据结构与算法就分享到此处,本月涉及数据结构与算法的内容有如下文章: <数据结构和算法对python意味着什么?> <顺序表数据结构在python中的应用> ...

  5. C学习笔记-基础数据结构与算法

    数据结构 数据(data)是对客观事物符号表示,在计算机中是指所有能输入的计算机并被计算机程序处理的数据总称. 数据元素(data element)是数据的基本单位,在计算机中通常做为一个整体进行处理 ...

  6. 数据结构与算法文章列表

    前言 数据结构与算法文章列表主要内容包括:稀疏数组.单向队列.环形队列.单向链表.双向链表.环形链表.约瑟夫问题.栈.前缀.中缀.后缀表达式.中缀表达式转换为后缀表达式.递归.迷宫问题.八皇后问题.散 ...

  7. 单向链表的有关操作(链式存储结构)

    ⑴随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序). ⑵遍历单向链表. ⑶把单向链表中元素逆置(不允许申请新的结点空间). ⑷在单向链表中删除所有的偶数元素结点. ⑸编写在非递减有序链表 ...

  8. 获取用户列表为空_数据结构和算法(Golang实现)(15)常见数据结构-列表

    列表 一.列表 List 我们又经常听到 列表 List 数据结构,其实这只是更宏观的统称,表示存放数据的队列. 列表 List:存放数据,数据按顺序排列,可以依次入队和出队,有序号关系,可以取出某序 ...

  9. vrp 节约算法 c++_数据结构和算法(Golang实现)(8.1)基础知识-前言

    基础知识 学习数据结构和算法.我们要知道一些基础的知识. 一.什么是算法 算法(英文algorithm)这个词在中文里面博大精深,表示算账的方法,也可以表示运筹帷幄的计谋等.在计算机科技里,它表示什么 ...

最新文章

  1. 用拉链法实现哈希算法的运算
  2. php安装gb,php安装程序的原理
  3. 在ubuntu 16.04下安装gitlab(摘抄中文官方网站)
  4. spring cloud教程之使用spring boot创建一个应用
  5. 建信金融科技春季全国笔试卷B编程题
  6. 用PHP做负载均衡指南
  7. 有限元python编程流行吗_Python进行有限元分析
  8. 【异常】No suitable driver
  9. 深度学习2.0-40.LSTM原理及实战
  10. DM9000有线网卡驱动编写
  11. 苏宁小店启动“三公里灯塔”计划 用服务造极社区生活圈
  12. java模拟微信抢红包金额算法规则二倍均值法模拟(满满的注释)
  13. 小甲鱼老师《带你学C带你飞》的后续课程补充
  14. pdf编辑导出word软件--Adobe Acrobat XI Pro
  15. 逆向工具之脱壳神器反射大师(附脱壳环境搭建、脱壳实战)
  16. linux 怎么看浏览器,Linux下浏览器比比看
  17. Qt环境报错-Project ERROR: Cannot run compiler ‘cl‘. Output
  18. 科普:24时区,GMT,UTC,DST,CST时间详解
  19. 2011年世界著名的杀毒软件排名是怎样的?
  20. ct系统与matlab成像,基于MATLAB的CT系统参数标定及成像研究

热门文章

  1. android 提醒app,安卓手机上提醒工作的软件有哪些?
  2. 计算机组装的品牌价格,相同配置的品牌电脑和组装电脑价格相差多少
  3. 如何看懂“听力图”?
  4. MapKeyboard键盘改键
  5. 图像DFT和DCT的频域真实频率
  6. 手把手带你玩转Spark机器学习-使用Spark构建回归模型
  7. python+playwright 学习-6.截图使用
  8. Vue项目开发中优雅的切换服务端ip
  9. 什么是 Java Mission Control?它是如何工作的?
  10. 【Java】Log4j日志