就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)
以下完整的代码,及测试代码均可从这里获取
https://github.com/Rain-Life/data-struct-by-go
常见的链表操作
单链表反转
方法一:就地反转法
思路
就地反转法,找一个空的节点来充当新的头结点(类似哨兵),然后遍历链表中每一个结点,将每一次遍历到的结点都插入到新的头结点后边,过程如下:
核心代码
- prev指针指向下一次需要反转的节点
- pcur指向待反转的节点
- 将待反转节点插入到newHead后边
prev.Next = pcur.Nextpcur.Next = newHead.NextnewHead.Next = pcurpcur = prev.Next
完整实现
func (list *List) ReverseList() { if list.headNode == nil { fmt.Println("链表为空") return }
newHead := &Node{} newHead.Next = list.headNode prevNode := newHead.Next currentNode := prevNode.Next
for currentNode != nil { prevNode.Next = currentNode.Next currentNode.Next = newHead.Next newHead.Next = currentNode currentNode = prevNode.Next } list.headNode = newHead.Next}
方法二:头插法
思路
这种方法比较简单,就是创建一个新的链表,将待反转的链表的每一个节点,通过头插法的方式,插入到新的链表中(关于单向链表、双向链表、循环链表、双向循环链表的操作,可以看我的上一篇文章)
核心代码
- pcur指向当前要插入的节点
- pnext指向下一个要插入的节点
- newHead为新链表的头结点
1 pnext = pcur.next2 pcur.Next = newHead.Next3 newHead.Next = pcur4 pcur = pnext
完整实现
func (list *List) ReverseListHead() { if list.headNode == nil { fmt.Println("链表为空") return }
newList := &List{} currentNode := list.headNode nextNode := currentNode.Next for currentNode!=nil { if newList.headNode == nil { newList.headNode = currentNode newList.headNode.Next = nil currentNode = nextNode continue } nextNode = currentNode.Next currentNode.Next = newList.headNode newList.headNode = currentNode currentNode = nextNode }
fmt.Println("反转后") newList.Traverse()}
循环链表中环的检测
思路
最简单的方式,通过快慢指针的方式处理。有两个指针lowPtr和fastPtr,它们同时从头结点开始遍历链表中的所有结点。lowPtr为慢指针,一次遍历一个结点;fastPtr为快指针,一次遍历两个结点
如果链表中没有环,则fastPtr和lowPtr会先后遍历完所有的结点
如果链表中有环,则快慢指针会先后进入到环中,并且一定会在某一个结点相遇。如果相遇,则该链表中是有环的
代码实现
func (list List) CheckRing() bool { if list.headNode == nil { fmt.Println("链表为空") return false }
low := list.headNode fast := list.headNode for fast.Next != nil { low = low.Next fast = fast.Next.Next
//为了防止for中fast.Next出现nil取Next,这里先做个判断 if fast == nil { return false } if low == fast { return true } }
return false}
用单向循环链表解决:约瑟夫问题
什么是约瑟夫问题
假设有n个人围成一圈,然后对每个人按顺序编号1,2,3,…,n,规定从1号按顺序开始报数,报到k的人出局,之后下一个人再从1开始报数,报到k的人在出局,一直进行下去,问:最后一个出局者为几号?
思路
解法有很多,但是最简单的方式,还是通过单向循环链表来解决。约瑟夫问题首先是一个环,环形链表恰好就非常适合来处理环形问题,将n个人看做环形链表中的每一个结点,当报到k之后便将该结点(人)从循环链表中删除,然后接着从下一个结点继续报数,直到链表为空
代码实现
func (list *List) DealJosephCircle(number int) []interface{} { var data []interface{} index := 1 currentNode := list.headNode preNode := list.headNode for preNode.Next != list.headNode { preNode = preNode.Next //刚开始,使preNode指向最后一个节点 }
for currentNode.Next != currentNode { if index == number { //删除结点,其实不用考虑是不是头结点或尾结点 data = append(data, currentNode.Data) preNode.Next = currentNode.Next currentNode = preNode.Next index = 1
continue } else { index++ } preNode = currentNode currentNode = currentNode.Next } data = append(data, currentNode.Data) currentNode = nil
return data}
往期文章
操作系统基础(十五)---使用fork系统调用创建进程
进程同步之共享内
时间复杂度和空间复杂度
IP协议详解
IT猿圈
不做开始爱好者
就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)相关推荐
- 数据结构排序算法实验报告_[数据结构与算法系列]排序算法(二)
我的上一篇文章向大家介绍了排序算法中的冒泡排序.插入排序和选择排序.它们都是平均时间复杂度为 O(n^2) 的排序算法,同时还为大家讲解了什么是原地排序和什么是排序的稳定性.下图是这三种算法的比较,不 ...
- 假设有搅乱顺序的一群儿童成一个队列_数据结构与算法系列之栈amp;队列(GO)...
以下完整代码均可从这里获取 栈 栈的基本概念 「后进先出.先进后出就是典型的栈结构」.栈可以理解成一种受了限制的线性表,插入和删除都只能从一端进行 当某个数据集合只涉及在一端插入和删除数据,并且满足后 ...
- 重学数据结构与算法系列:链表及其应用
引言 链表是非常常用的基础数据结构,我们经常把它和数组放在一起进行比较.那我们首先来看下这两个常用的数据结构各自的特点是什么吧. 我们在实际编程的时候,如果进行数组的定义,那么就需要向系统申请连续的内 ...
- node 获取表单数据 为空_数据结构与算法(python)单向链表篇
链表 数据表的构建需要预先知道数据的大小来申请连续的存储空间, 而在进行扩充的时候又需要进行数据的搬迁, 使用起来不是很灵活. 链表结构可以充分利用计算机内存空间, 实现灵活的内存动态管理. 简单来说 ...
- a*算法的时间复杂度_数据结构与算法系列——时间、空间复杂度
数据结构和算法本质就是帮我们用最快的时间和最少的空间来执行我们的代码.所以,执行效率是衡量一个算法的非常重要的指标.那如何来计算你的算法代码的执行效率呢?这就需要时间.空间复杂度来分析了. 有人可能会 ...
- 一层循环时间复杂度_数据结构与算法系列——时间、空间复杂度
数据结构和算法本质就是帮我们用最快的时间和最少的空间来执行我们的代码.所以,执行效率是衡量一个算法的非常重要的指标.那如何来计算你的算法代码的执行效率呢?这就需要时间.空间复杂度来分析了. 有人可能会 ...
- java 快速从树节点找到数据_数据结构与算法:单向链表和双向链表
一.链表简介 1.链表概念 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列节点组成,节点可以在运行时动态生成,节点包括两个部分:一个 ...
- java 单链表是否有环_数据结构与算法随笔之链表-链表是否有环(二)
上一篇文章我们分析了下链表之反转单向链表,这篇文章我们来分析下另外一个关于链表的经典题目. 判断链表是否有环(在leetcode上的题目地址:环形链表) 题目描述 给定一个链表,判断链表中是否有环 解 ...
- 高度平衡二叉树的构建_数据结构与算法系列(十六)平衡二叉树的构建实现过程演示...
我们在上一篇文章中分享了平衡二叉树的定义和实现原理,这一节我们来演示如何通过代码实现平衡二叉树,最后分析下平衡二叉树的算法复杂度. 实例演示 在开始之前,我们先通过一个对比来加强理解,在没有介绍平衡二 ...
最新文章
- 数字图像基本处理算法小结
- MVP架构设计 进阶三
- php 修改文件的权限_php怎么修改文件的权限?
- iis授权mysql验证_ASP.NET Web API身份验证和授权
- 计算机健康教育应用的意义,健康教育路径计算机模块的建立与应用 (3)
- commonJs原理解析
- 想系统化提升自己产品能力,就要读这些书籍
- 收藏10个2012年最新发布的jQuery插件
- JSP Cookie 处理
- mysql 存储过程参数集合_MySQL存储过程
- 华山论剑之JAVA三大代码生成工具:Lombok、AutoValue和Immutables
- 小猪cms之怎样查询绑定的微网站模板
- 淘宝客升级助手V1.0 等级升级获取高级账户,淘客适用高佣金破解版
- 频数直方图的步骤_超级详细的直方图应用步骤及分析,一篇搞定直方图!
- ftm模块linux驱动,飞思卡尔K60 FTM模块详解【二】
- Android 阻止AlertDialog dismiss
- Canvas实例之鼠标移动特效(彩色小球)
- 【CTF练习平台】BugkuCTF部分misc writeup
- DZY Loves Sequences (dp)
- MS8422/MS8413/MS8412/MS8416音频光纤同轴解码芯片样品技术支持
热门文章
- 形态学上的图像顶帽运算和黑帽运算是什么?
- 为什么这款 CPU 在亚马逊上卖得最火?
- 用 Java 语言,写一个植物大战僵尸简易版!
- 为何各家抢滩物联网?
- 刚在乌镇夺魁的飞桨,又将在“WAVE SUMMIT+”深度学习开发者峰会带来哪些惊喜?...
- 华为研发雄起加拿大!
- 女生,到底能不能当程序员?
- 华为小米入场,能拯救乐视互联网电视挖的坑吗?
- 可以抛弃 Python 了?Google 开源 Swift for TensorFlow 意味着什么
- 天天 Java、C/C++,可这五种编程语言你知道吗?