共计 19153 个字符,预计需要花费 48 分钟才能阅读完成。
前言
这里不介绍链表是什么之类的概念,大家能够找一找相干的书籍或文章看看,本文次要是用 GO 来实现一些链表的操作
阐明:刚开始学习 GO,可能用到的实现办法不是最简便的,意思表达出来了就能够,大家凑合着看【手动狗头】。如有谬误,欢送斧正
以下的代码均可从这里获取
https://github.com/Rain-Life/learnGo
播种:做链表的题,肯定!肯定!肯定!要画图!要画图!要画图!不然,特地容易乱,很难一遍写出 0 error,0 warning 的链表代码
链表
单链表的基本操作
链表通过指针将一组零散的内存块串联在一起,这里的内存块称为链表的 结点 。为了将这些节点给串起来,每个链表的结点除了存储数据之外,还会记录下一个结点的指针(即下一个结点的地址),这个指针称为: 后继指针
定义单链表根本构造
定义链表构造
// 定义结点中数据的类型为接口类型,可收任意类型数据
type Object interface {}
// 定义结点的构造体
type Node struct {
Data Object
Next *Node
}
// 定义链表的构造体
type List struct {headNode *Node}
判断链表是否为空
func (list *List) IsEmpty() bool {
if list.headNode == nil {return true}
return false
}
获取链表的长度
func (list *List) Length() int {
currentNode := list.headNode
count := 0
for currentNode != nil {
count++
currentNode = currentNode.Next
}
return count
}
增加结点
向链表头部增加结点
func (list *List) AddFromHead(data Object) *Node {node := &Node{Data:data}
if list.IsEmpty() {
list.headNode = node
return node
}
node.Next = list.headNode
list.headNode = node
return node
}
向链表尾部增加结点
func (list *List) Append(data Object) {node := &Node{Data: data}
if list.IsEmpty() {list.headNode = node} else {
currentNode := list.headNode
for currentNode.Next != nil {currentNode = currentNode.Next}
currentNode.Next = node
}
}
向链表中指定地位增加结点
func (list *List) Insert(position int, data Object) {
if position <= 1 {list.AddFromHead(data)
} else if position > list.Length() {list.Append(data)
} else {
pre := list.headNode
count := 1
for count < (position-1) {
pre = pre.Next
count++
}// 循环退出当前 pre 刚好在 position- 1 的地位
node := &Node{Data: data}
node.Next = pre.Next
pre.Next = node
}
}
删除结点
删除链表头部结点
func (list *List) RemoveHeadNde() Object {if list.IsEmpty() {fmt.Println("链表为空")
return nil
}
currentNode := list.headNode
if list.headNode.Next == nil {
list.headNode = nil
return currentNode.Data
}
list.headNode = currentNode.Next
return currentNode.Data
}
删除链表尾部结点
func (list *List) RemoveLastNode() Object {if list.IsEmpty() {return "链表为空"}
currentNode := list.headNode
for currentNode.Next.Next != nil {currentNode = currentNode.Next}
data := currentNode.Next.Data
currentNode.Next = nil
return data
}
删除指定值的结点
func (list *List) Remove(data Object) {
pre := list.headNode
if pre.Data == data{list.headNode = pre.Next} else {
for pre.Next != nil {
if pre.Next.Data == data {pre.Next = pre.Next.Next} else {pre = pre.Next}
}
}
}
删除指定地位的结点
func (list *List) RemovePosition(position int) {
pre := list.headNode
if position <= 1 {list.headNode = nil} else if position > list.Length() {fmt.Println("超出链表长度")
} else {
count :=1
for count != position-1 && pre.Next != nil {
count++
pre = pre.Next
}
pre.Next = pre.Next.Next
}
}
查找结点
链表中是否蕴含某个值的节点
func (list *List) Contain(data Object) bool {
currentNode := list.headNode
for currentNode != nil {
if currentNode.Data == data {return true}
currentNode = currentNode.Next
}
return false
}
遍历链表
遍历
func (list *List) Traverse() {if list.IsEmpty() {fmt.Println("链表为空")
}
currentNode := list.headNode
for currentNode != nil {fmt.Printf("%v\t", currentNode.Data)
currentNode = currentNode.Next
}
}
测试
package main
import (
"fmt"
"learnGo/linkedList/node"
)
func print(list node.List) {fmt.Printf("链表长度 %d\n", list.Length())
fmt.Println("遍历链表所有结点:")
list.Traverse()
fmt.Println()
fmt.Println()}
func main() {list := node.List{}
// 向链表的尾部追加元素
fmt.Println("++++++++1、向链表尾部追加结点 ++++++++")
list.Append(3)
list.Append(8)
list.Append(1)
list.Append(9)
list.Append("PHP")
list.Append("Golang")
list.Append("Java")
list.Append("JavaScript")
print(list)
fmt.Println("++++++++2、判断链表是否为空 ++++++++")
fmt.Printf("链表是否为空:%v", list.IsEmpty())
fmt.Println()
fmt.Println()
// 向链表的头部增加元素
fmt.Println("++++++++3、向链表的头部增加一个结点 ++++++++")
fmt.Println()
list.AddFromHead("firstNode")
print(list)
fmt.Println("++++++++4、向链表尾部增加结点 ++++++++")
fmt.Println()
list.Append("lastNode")
print(list)
fmt.Println("++++++++5、向链表尾部增加结点 ++++++++")
fmt.Println()
list.Insert(3, "thirdNode")
print(list)
fmt.Println("++++++++6、删除链表头结点 ++++++++")
fmt.Println()
list.RemoveHeadNde()
print(list)
fmt.Println("++++++++7、删除链表尾结点 ++++++++")
fmt.Println()
list.RemoveLastNode()
print(list)
fmt.Println("++++++++8、删除链表中指定值的结点 ++++++++")
fmt.Println()
list.Remove(9)
print(list)
fmt.Println("++++++++9、删除链表中指定地位的结点 ++++++++")
fmt.Println()
list.RemovePosition(3)
print(list)
fmt.Println("++++++++10、查问链表中是否蕴含某一个结点 ++++++++")
fmt.Println()
res := list.Contain("Golang")
fmt.Printf("是否存在 Golang 结点:%v\n", res)
print(list)
}
实现各种类型的链表
各种链表简介
循环链表
循环链表是一种非凡的单链表。循环跟单链表惟一的区别就在 尾结点 。单链表的尾结点指针指向 空地址 ,示意这就是最初的结点了。而 循环链表的尾结点指针是指向链表的头结点
循环链表的长处就是,从链尾到链头比拟不便。当要解决的数据具备 环型构造 特点时,就特地适宜采纳循环链表
双向链表
和单向链表相比,双向链表有两个指针,指向前一个结点的指针是 前驱指针 (prev),指向后一个结点的是 后继指针(next)
有了前驱指针,能够更加不便的获取以后结点的前一个结点。依照单链表的形式,咱们如果要获取前驱结点,要么遍历的时候用一个变量来保留前驱结点,要么再次遍历获取前驱结点。而双向链表能够在 O(1)复杂度下找到前驱结点
单向链表和双向链表比照
- 如果存储同样多的数据,双向链表要比单链表占用更多的内存空间。尽管两个指针比拟节约存储空间,但能够反对双向遍历,这样也带来了双向链表操作的灵活性
- 双向链表的插入和删除操作更高效,因为能够很容易获取到前驱结点
- 如果有一个有序的链表,双向链表的按值查问的效率也要比单链表高一些。因为,咱们能够记录上次查找的地位 p,每次查问时,依据要查找的值与 p 的大小关系,决定是往前还是往后查找,所以均匀只须要查找一半的数据
双向链表只管比拟费内存,但还是比单链表的利用更加宽泛的起因是 空间换工夫的思维
当内存空间短缺的时候,如果咱们更加谋求代码的执行速度,咱们就能够抉择空间复杂度绝对较高、但工夫复杂度绝对很低的算法或者数据结构。相同,如果内存比拟紧缺,比方代码跑在手机或者单片机上,这个时候,就要反过来用工夫换空间的设计思路
起源:数据结构与算法之美
双向循环链表
将循环链表和双向链表联合,失去的就是:双向循环链表
各种类型的链表操作
这部分间接上代码了
循环链表
这里间接放残缺的各种操作的代码,重点中央会加上阐明
loopLinkedList.go
package loopLinkList
import "fmt"
// 循环链表
type Object interface {}
type Node struct {
Data Object
Next *Node
}
type List struct {headNode *Node}
// 判断循环链表是否为空(与单链表的实现没有区别)func (list *List) IsEmpty() bool {
if list.headNode == nil {return true}
return false
}
// 获取循环链表的长度(与单链表的获取长度区别在于循环的终止条件)func (list *List) Length() int {
if list.headNode == nil {return 0}
currentNode := list.headNode
count := 1
for currentNode.Next != list.headNode {
count++
currentNode = currentNode.Next
}
return count
}
// 向循环链头部增加结点
func (list *List) AddFromHead(data Object) {node := &Node{Data: data}
// 链表为空的状况
if list.IsEmpty() {
list.headNode = node
list.headNode.Next = list.headNode // 单链表没有这一步
} else {
currentNode := list.headNode
for currentNode.Next != list.headNode { // 须要先找到最初一个结点
currentNode = currentNode.Next
}
node.Next = list.headNode
currentNode.Next = node // 单链表没有这一步操作,将最初一个节点的 next 指向头结点
list.headNode = node
}
}
// 向循环链表的尾部增加结点
func (list *List) Append(data Object) {node := &Node{Data: data}
if list.IsEmpty() {
list.headNode = node
list.headNode.Next = node
} else {
currentNode := list.headNode
for currentNode.Next != list.headNode {currentNode = currentNode.Next}
currentNode.Next = node
node.Next = list.headNode // 单链表没有这一步操作(让最初一个节点指向头结点)}
}
// 向循环链表的指定地位增加结点(跟单链表是一样的)func (list *List) Insert(position int, data Object) {
if position <= 1 {list.AddFromHead(data)
} else if position > list.Length() {list.Append(data)
} else {
currentNode := list.headNode
count := 1
for count < position-1 {
currentNode = currentNode.Next
count++
}
node := &Node{Data: data}
node.Next = currentNode.Next
currentNode.Next = node
}
}
// 删除循环链表的头结点
func (list *List) RemoveHeadNde() {if list.IsEmpty() {fmt.Println("链表是空的")
return
}
currentNode := list.headNode
lastNode := list.headNode
// 思考循环链表只有一个结点的状况
if currentNode.Next == list.headNode {
list.headNode = nil
return
}
for lastNode.Next != list.headNode {lastNode = lastNode.Next}
list.headNode = currentNode.Next
lastNode.Next = list.headNode
}
// 删除循环链表的尾结点
func (list *List) RemoveLastNode() {if list.IsEmpty() {fmt.Println("链表是空的")
return
}
currentNode := list.headNode
// 思考循环链表只有一个结点的状况
if currentNode.Next == list.headNode {
list.headNode = nil
return
}
for currentNode.Next.Next != list.headNode {currentNode = currentNode.Next}
currentNode.Next = list.headNode
}
// 删除循环链表中指定地位的节点 (需思考删除的结点是不是第一个或最初一个)
func (list *List) RemovePosition(position int) {if list.IsEmpty() {fmt.Println("链表为空")
return
}
if position <= 1 {list.RemoveHeadNde()
} else if position > list.Length() {list.RemoveLastNode()
} else {
currentNode := list.headNode
count := 1
if count != position-1 && currentNode.Next != list.headNode{
count++
currentNode = currentNode.Next
}
currentNode.Next = currentNode.Next.Next
}
}
// 删除循环链表中指定值的结点
func (list *List) Remove(data Object) {if list.IsEmpty() {fmt.Println("链表为空")
return
}
currentNode := list.headNode
// 删除的结点为头结点时
if currentNode.Data == data {list.RemoveHeadNde()
return
}
for currentNode.Next != list.headNode {
if currentNode.Next.Data == data {
currentNode.Next = currentNode.Next.Next
return
} else {currentNode = currentNode.Next}
}
if currentNode.Next == list.headNode {list.RemoveLastNode()
}
}
// 查找循环链表中指定结点
func (list *List) Contain(data Object) bool {if list.IsEmpty() {return false}
currentNode := list.headNode
for currentNode.Next != list.headNode {
if currentNode.Data == data {return true}
currentNode = currentNode.Next
}
if currentNode.Data == data {return true}
return false
}
// 遍历循环链表
func (list *List) Traverse() {if list.IsEmpty() {fmt.Println("循环链表为空")
return
}
currentNode := list.headNode
if currentNode.Next == list.headNode { // 兼容循环链表只有一个结点的状况
fmt.Printf("%v\t", currentNode.Data)
return
}
for currentNode.Next != list.headNode {fmt.Printf("%v\t", currentNode.Data)
currentNode = currentNode.Next
}
fmt.Printf("%v\t", currentNode.Data)
}
entry.go(测试)
package main
import (
"fmt"
"learnGo/linkedList/loopLinkList"
)
func print(list loopLinkList.List) {fmt.Printf("链表长度:%d\n", list.Length())
fmt.Println("遍历链表所有结点:")
list.Traverse()
fmt.Println()
fmt.Println()}
func main() {list := loopLinkList.List{}
fmt.Println("++++++++1、判断链表是否为空 ++++++++")
fmt.Printf("链表是否为空:%v\n", list.IsEmpty())
print(list)
fmt.Println("++++++++2、获取链表长度 ++++++++")
fmt.Printf("获取链表长度:%d\n", list.Length())
print(list)
fmt.Println("++++++++3、向循环链头部增加结点 ++++++++")
list.AddFromHead("firstNode")
print(list)
fmt.Println("++++++++4、向循环链尾部增加结点 ++++++++")
list.Append("lastNode")
print(list)
fmt.Println("++++++++5、向循环链指定地位增加结点 ++++++++")
list.Insert(1,"secondNode")
print(list)
fmt.Println("++++++++6、删除循环链的头结点 ++++++++")
list.RemoveHeadNde()
print(list)
fmt.Println("++++++++7、删除循环链的尾结点 ++++++++")
list.RemoveLastNode()
print(list)
fmt.Println("++++++++8、查找循环链表中指定结点 ++++++++")
fmt.Printf("是否蕴含 secondNode 节点:%v\n", list.Contain("secondNode"))
print(list)
fmt.Println("++++++++9、删除循环链表中指定地位的结点 ++++++++")
list.RemovePosition(1)
print(list)
fmt.Println("++++++++10、删除循环链表中指定值的结点 ++++++++")
list.Remove("lastNode")
print(list)
}
双向链表
doublyLinkedList.go
package doublyLinkedList
import ("fmt")
// 双向链表
type Object interface {}
type Node struct {
Data Object
Prev,Next *Node
}
type List struct {headNode *Node}
// 阐明
/**
1、如果结点的 Next 指向为 null,则阐明是最初一个结点
2、第一个结点的 prev 指向为空
3、双向链表和单向链表差不多,区别就是删除和增加结点的时候更不便了,因为很不便的能够获取到前一个结点
*/
// 判断双向链表是否为空
func (list *List) IsEmpty() bool {
if list.headNode == nil {return true}
return false
}
// 遍历双向链表(跟遍历单链表截然不同)func (list *List) Traverse() {if list.IsEmpty() {fmt.Println("双线链表为空")
return
}
currentNode := list.headNode
for currentNode != nil {fmt.Printf("%v\t", currentNode.Data)
currentNode = currentNode.Next
}
}
// 获取双向链表的长度(跟获取单链表长度截然不同)func (list *List) Length() int {if list.IsEmpty() {return 0}
count := 0
currentNode := list.headNode
for currentNode != nil {
count++
currentNode = currentNode.Next
}
return count
}
// 从双向链表头部开始减少结点
func (list *List) AddFromHead(data Object) *Node {node := &Node{Data: data}
if list.IsEmpty() {
list.headNode = node
return node
}
list.headNode.Prev = node
node.Next = list.headNode
list.headNode = node
return node
}
// 从双向链表尾部增加结点
func (list *List) Append(data Object) {node := &Node{Data: data}
if list.IsEmpty() {list.headNode = node} else {
currentNode := list.headNode
for currentNode.Next != nil {currentNode = currentNode.Next}
currentNode.Next = node
node.Prev = currentNode
}
}
/**
* 向双向链表的指定地位插入结点
*
* 阐明:在单向链表中,我是通过找到我要插入的这个结点的前一个结点,而后将要插入的结点,* 插入到这个结点的后边(因为插入结点须要找到以后结点的前一个结点,为了防止再次遍历找前一个结点,所以采纳了这种形式)* 而双向链表就不须要这么做了,找到指定地位的结点,新的插入到它前边就能够了
*/
func (list *List) Insert(position int, data Object) {
if position <= 1 {list.AddFromHead(data)
} else if position > list.Length() {list.Append(data)
} else {
currentNode := list.headNode
count := 1
for count != position {
currentNode = currentNode.Next
count++
}
// 找到了指定地位的结点,而后将要插入的结点,插到这个节点前边即可(留神程序,画图最容易了解)
node := &Node{Data: data}
node.Next = currentNode
node.Prev = currentNode.Prev
currentNode.Prev.Next = node
currentNode.Prev = node
}
}
// 删除链表头结点
func (list *List) RemoveHeadNde() Object {if list.IsEmpty() {fmt.Println("链表为空")
return nil
}
currentNode := list.headNode
if currentNode.Next == nil && currentNode.Prev == nil {
list.headNode = nil
return currentNode.Data
}
list.headNode = currentNode.Next
currentNode.Prev = nil
return currentNode.Data
}
// 删除链表尾结点
func (list *List) RemoveLastNode() Object {if list.IsEmpty() {fmt.Println("链表为空")
return nil
}
if list.headNode.Next == nil {list.headNode = nil}
currentNode := list.headNode
for currentNode.Next != nil {currentNode = currentNode.Next}
currentNode.Prev.Next = nil
return currentNode.Prev.Data
}
// 删除双向表中指定值的结点
func (list *List) Remove(data Object) {if list.IsEmpty() {fmt.Println("链表为空")
return
}
currentNode := list.headNode
if list.headNode.Next == nil && list.headNode.Data == data {list.headNode = nil}
fmt.Println(data, currentNode.Data, currentNode.Data == data)
for currentNode != nil {
if currentNode.Data == data && currentNode == list.headNode {list.headNode = currentNode.Next} else if currentNode.Data == data && currentNode.Prev != nil {
currentNode.Prev.Next = currentNode.Next
currentNode.Next.Prev = currentNode.Prev
} else {currentNode = currentNode.Next}
}
}
// 删除双向链表中指定地位的结点
func (list *List) RemovePosition(position int) {if list.IsEmpty() {fmt.Println("链表为空")
return
}
if position <=1 {list.RemoveHeadNde()
} else if position > list.Length() {list.RemoveLastNode()
} else {
currentNode := list.headNode
count := 1
for count != position {
count++
currentNode = currentNode.Next
}
currentNode.Prev.Next = currentNode.Next
currentNode.Next.Prev = currentNode.Prev
}
}
// 查问双向链表中是否蕴含某一个结点(和单向链表一样)
func (list *List) Contain(data Object) bool {if list.IsEmpty() {fmt.Println("链表为空")
return false
}
currentNode := list.headNode
for currentNode != nil {
if currentNode.Data == data {return true}
currentNode = currentNode.Next
}
return false
}
entry.go(测试)
package main
import (
"fmt"
"learnGo/linkedList/doublyLinkedList"
)
func print(list doublyLinkedList.List) {fmt.Printf("链表长度 %d\n", list.Length())
fmt.Println("遍历链表所有结点:")
list.Traverse()
fmt.Println()
fmt.Println()}
func main() {list := doublyLinkedList.List{}
fmt.Println("++++++++1、判断链表是否为空 ++++++++")
fmt.Printf("链表是否为空:%v", list.IsEmpty())
fmt.Println()
fmt.Println()
fmt.Println("++++++++2、向双向链表头部增加元素 ++++++++")
fmt.Println()
list.AddFromHead(1)
list.AddFromHead(2)
list.AddFromHead(3)
print(list)
fmt.Println("++++++++3、向双向链表尾部增加元素 ++++++++")
fmt.Println()
list.Append("Golang")
list.Append("PHP")
list.Append("Java")
print(list)
fmt.Println("++++++++4、向双向链表的指定地位插入结点 ++++++++")
fmt.Println("++++++++(1)向双向链表的【第一个】地位插入结点 ++++++++")
list.Insert(1, "First")
print(list)
fmt.Println("++++++++(2)向双向链表的【第三个】地位插入结点 ++++++++")
list.Insert(3, "Third")
print(list)
fmt.Println("++++++++(3)向双向链表的【最初】地位插入结点 ++++++++")
list.Insert(list.Length()+1, "Last")
print(list)
fmt.Println("++++++++5、删除双向链表的头结点 ++++++++")
fmt.Println()
list.RemoveHeadNde()
print(list)
fmt.Println("++++++++6、删除双向链表的尾结点 ++++++++")
fmt.Println()
list.RemoveLastNode()
print(list)
fmt.Println("++++++++7、删除双向表中指定值的结点 ++++++++")
list.Remove(3)// 这里的类型要和你插入时的类型统一(弱类型语言写习惯了,很容易忘了)print(list)
fmt.Println("++++++++8、删除双向表中指定地位的结点 ++++++++")
fmt.Println("++++++++(1)删除双向链表的【第一个】地位结点 ++++++++")
list.RemovePosition(1)
print(list)
fmt.Println("++++++++(2)删除双向链表的【第三个】地位结点 ++++++++")
list.RemovePosition(3)
print(list)
fmt.Println("++++++++(3)删除双向链表的【最初】地位结点 ++++++++")
list.RemovePosition(list.Length())
print(list)
fmt.Println("++++++++9、查问双向链表中是否蕴含某一个结点 ++++++++")
fmt.Println()
fmt.Printf("是否存在 Golang 结点:%v\n", list.Contain(2))
}
双向循环链表
doublyLoopLinkedList.go
package doublyLoopLinkedList
import ("fmt")
type Object interface {}
type Node struct {
Data Object
Prev,Next *Node
}
type List struct {headNode *Node}
// 判断双向循环链表是否为空
func (list *List) IsEmpty() bool {
if list.headNode == nil {return true}
return false
}
// 遍历双向循环链表
func (list *List) Traverse() {if list.IsEmpty() {fmt.Println("链表为空")
return
}
if list.headNode.Next == nil {// 兼容双向循环链表只有一个结点的状况
fmt.Printf("%v\t", list.headNode.Data)
return
}
currentNode := list.headNode
for currentNode.Next != list.headNode {fmt.Printf("%v\t", currentNode.Data)
currentNode = currentNode.Next
}
fmt.Printf("%v\t", currentNode.Data)
}
// 获取双向循环链表的长度
func (list *List) Length() int {if list.IsEmpty() {return 0}
count := 1
currentNode := list.headNode
for currentNode.Next != list.headNode {
count++
currentNode = currentNode.Next
}
return count
}
// 从双向循环链表头部增加结点(肯定肯定要画图,比拟好了解)
func (list *List) AddFromHead(data Object) *Node {node := &Node{Data: data}
if list.IsEmpty() {
list.headNode = node
return node
}
currentNode := list.headNode
if currentNode.Next == nil { // 思考只有一个节点的时候
node.Prev = currentNode
currentNode.Next = node
node.Next = currentNode
currentNode.Prev = node
list.headNode = node
return node
}
node.Prev = currentNode.Prev
currentNode.Prev.Next = node
currentNode.Prev = node
node.Next = currentNode
list.headNode = node
return node
}
// 从双向循环链表尾部增加结点
func (list *List) Append(data Object) *Node {node := &Node{Data: data}
if list.IsEmpty() {
list.headNode = node
return node
}
currentNode := list.headNode
currentNode.Prev.Next = node
node.Prev = currentNode.Prev
currentNode.Prev = node
node.Next = currentNode
return node
}
// 向双向循环链表的指定地位插入结点
func (list *List) Insert(position int, data Object) {
if position <=1 {list.AddFromHead(data)
} else if position > list.Length() {list.Append(data)
} else {node := &Node{Data: data}
currentNode := list.headNode
count := 1
for count != position {
count++
currentNode = currentNode.Next
}
// 将待插入的节点插入到以后节点的前边即可(这块的逻辑其实和双向链表的在两头位子插入结点逻辑一样)
currentNode.Prev.Next = node
node.Prev = currentNode.Prev
currentNode.Prev = node
node.Next = currentNode
}
}
// 删除双向循环链表头结点
func (list *List) RemoveHeadNde() Object {if list.IsEmpty() {fmt.Println("双向循环链表为空")
return ""
}
currentNode := list.headNode
if currentNode.Next == nil {// 只有一个结点的状况
list.headNode = nil
return currentNode.Data
}
currentNode.Prev.Next = currentNode.Next
currentNode.Next.Prev = currentNode.Prev
list.headNode = currentNode.Next
return currentNode.Data
}
// 删除双向循环链表尾结点
func (list *List) RemoveLastNode() Object {if list.IsEmpty() {fmt.Println("双向循环链表为空")
return ""
}
currentNode := list.headNode
if currentNode.Next == nil {// 只有一个结点的状况
list.headNode = nil
return list.headNode.Data
}
lastNode := list.headNode.Prev
lastNode.Prev.Next = currentNode
currentNode.Prev = lastNode.Prev
return lastNode.Data
}
// 删除双向循环链表中指定值的结点
func (list *List) Remove(data Object) bool {if list.IsEmpty() {fmt.Println("双向循环链表为空")
return false
}
// 如果链表只有一个节点
if list.headNode.Next == nil {
if list.headNode.Data == data {
list.headNode = nil
return true
}
return false
}
currentNode := list.headNode
// 如果值刚好等于第一个节点的值
if currentNode.Data == data {list.RemoveHeadNde()
return true
}
// 如果值刚好等于最初一个结点的值
for currentNode.Next != list.headNode {
if currentNode.Data == data {
// 删除两头节点
currentNode.Prev.Next = currentNode.Next
currentNode.Next.Prev = currentNode.Prev
return true
} else {currentNode = currentNode.Next}
}
if currentNode.Data == data { // 刚好是最初一个结点的时候
list.RemoveLastNode()
return true
}
return false
}
// 删除双向循环链表中指定地位的结点
func (list *List) RemovePosition(position int) {if list.IsEmpty() {fmt.Println("双向循环链表为空")
return
}
if position <= 1 {list.RemoveHeadNde()
} else if position > list.Length() {list.RemoveLastNode()
} else {
currentNode := list.headNode
count := 1
for count != position {
count++
currentNode = currentNode.Next
}
currentNode.Prev.Next = currentNode.Next
currentNode.Next.Prev = currentNode.Prev
}
}
// 查问双向循环链表中是否蕴含某一个结点(跟循环链表的查找逻辑一样)
func (list *List) Contain(data Object) bool {if list.IsEmpty() {fmt.Println("双向循环链表为空")
return false
}
currentNode := list.headNode
for currentNode.Next != list.headNode {
if currentNode.Data == data {return true}
currentNode = currentNode.Next
}
if currentNode.Data == data {return true}
return false
}
entry.go
package main
import (
"fmt"
"learnGo/linkedList/doublyLoopLinkedList"
)
func print(list doublyLoopLinkedList.List) {fmt.Printf("链表长度 %d\n", list.Length())
fmt.Println("遍历链表所有结点:")
list.Traverse()
fmt.Println()
fmt.Println()}
func main() {list := doublyLoopLinkedList.List{}
fmt.Println("++++++++1、判断链表是否为空 ++++++++")
fmt.Printf("链表是否为空:%v", list.IsEmpty())
fmt.Println()
fmt.Println()
fmt.Println("++++++++2、向双向循环链表头部增加结点 ++++++++")
fmt.Println()
list.AddFromHead(1)
list.AddFromHead(2)
list.AddFromHead(3)
print(list)
fmt.Println("++++++++3、向双向循环链表尾部增加结点 ++++++++")
fmt.Println()
list.Append("lastNode")
print(list)
fmt.Println("++++++++4、向双向循环链表指定地位增加结点 ++++++++")
fmt.Println()
list.Insert(1,"firstNode")
print(list)
fmt.Println("++++++++5、删除双向循环链表头结点 ++++++++")
fmt.Println()
list.RemoveHeadNde()
print(list)
fmt.Println("++++++++6、删除双向循环链表尾结点 ++++++++")
fmt.Println()
list.RemoveLastNode()
print(list)
fmt.Println("++++++++7、删除双向循环链表中指定值的结点 ++++++++")
fmt.Println()
list.Remove(1)
print(list)
fmt.Println("++++++++8、删除双向循环链表中指定地位的结点 ++++++++")
fmt.Println()
list.RemovePosition(list.Length()-1)
print(list)
fmt.Println("++++++++9、查问双向循环链表中是否蕴含某一个结点 ++++++++")
fmt.Println()
fmt.Println("是否蕴含值为 firstNode 的结点:", list.Contain("firstNode"))
print(list)
}
小白一枚,记录点滴成长,公众号:IT 猿圈
次要记录:操作系统、计算机网络、编译原理、数据结构和算法
参考:
《数据结构与算法之美》