单向链表的问题:

  1. 单向链表只能一个方向查找,双向链表可以向前也可以向后查找(前后两个方向查找
  2. 单向链表不能自我删除,,需要考辅助节点。双向链表可以自我删除

    示意图

    image.png
    image.png
    image.png

    注意:

  3. 按顺序插入 ```go // newNode 应该插入 temp.next 前面, temp后面 newNode.next = temp.next newNode.pre = temp

if temp.next != nil { temp.next.pre = newNode }

temp.next = newNode

  1. 2. 删除节点
  2. ```go
  3. // 删除, 更改节点指向
  4. temp.next = temp.next.next
  5. // 判断是否是最后一个
  6. if temp.next != nil {
  7. temp.next.pre = temp
  8. }

代码实现

  1. // 双向链表 - 增删改查
  2. package main
  3. import (
  4. "fmt"
  5. )
  6. // 定义节点
  7. type HeroNode struct {
  8. no int
  9. name string
  10. nickname string
  11. pre *HeroNode // 表示指向前一个节点
  12. next *HeroNode // 表示指向下一个节点
  13. }
  14. // 添加节点
  15. func insertNode(head *HeroNode, newNode *HeroNode) {
  16. // 1. 找到链表最后的节点
  17. // 2. 创建辅助节点, 跑龙套的
  18. temp := head
  19. for {
  20. if temp.next == nil {
  21. // 最后的节点
  22. break
  23. }
  24. temp = temp.next // temp 一直后移, 直到指向链表最后的节点
  25. }
  26. // 3. 修改 temp 节点的 next 指向 newNode, 并将新节点的 pre 指向 temp
  27. temp.next = newNode
  28. newNode.pre = temp
  29. }
  30. // 根据 编号 no 插入到指定位置(从小到大)
  31. func insertNode02(head *HeroNode, newNode *HeroNode) {
  32. // 1. 找到链表适当的节点
  33. // 2. 创建辅助节点, 跑龙套的
  34. temp := head
  35. flag := true
  36. for {
  37. if temp.next == nil {
  38. // 最后的节点
  39. break
  40. } else if temp.next.no > newNode.no {
  41. // 升降序, 只需要修改 temp.next.no < newNode.no
  42. break
  43. } else if temp.next.no == newNode.no {
  44. fmt.Println("已经存在,不允许加入")
  45. flag = false
  46. break
  47. }
  48. temp = temp.next // temp 一直后移,
  49. }
  50. if !flag {
  51. fmt.Println("不能插入节点")
  52. return
  53. } else {
  54. // newNode 应该插入 temp.next 前面, temp后面
  55. newNode.next = temp.next
  56. newNode.pre = temp
  57. if temp.next != nil {
  58. temp.next.pre = newNode
  59. }
  60. temp.next = newNode
  61. }
  62. }
  63. // 删除节点
  64. func delNode(head *HeroNode, id int) {
  65. // 1. 先来一个跑龙套的
  66. temp := head
  67. flag := false
  68. // 2. 找到要删除的节点
  69. for {
  70. if temp.next == nil {
  71. break
  72. } else if temp.next.no == id {
  73. // 找到了
  74. flag = true
  75. break
  76. }
  77. temp = temp.next
  78. }
  79. if flag {
  80. // 删除, 更改节点指向
  81. temp.next = temp.next.next
  82. // 判断是否是最后一个
  83. if temp.next != nil {
  84. temp.next.pre = temp
  85. }
  86. } else {
  87. fmt.Println("要删除的节点id不存在")
  88. }
  89. }
  90. // 显示链表所有节点信息
  91. func showNode(head *HeroNode) {
  92. // 1. 创建辅助节点, 跑龙套的
  93. temp := head
  94. // 2. 判断该链表是不是空的
  95. if temp.next == nil {
  96. fmt.Println("空链表")
  97. return
  98. }
  99. // 2. 遍历链表
  100. for {
  101. fmt.Printf("[%d , %s , %s] => ", temp.next.no, temp.next.name, temp.next.nickname)
  102. temp = temp.next
  103. if temp.next == nil {
  104. break
  105. }
  106. }
  107. fmt.Println()
  108. }
  109. // 逆序 显示链表所有节点信息
  110. func showNode02(head *HeroNode) {
  111. // 1. 创建辅助节点, 跑龙套的
  112. temp := head
  113. // 2. 判断该链表是不是空的
  114. if temp.next == nil {
  115. fmt.Println("空链表")
  116. return
  117. }
  118. // temp 定位到最后节点
  119. for {
  120. if temp.next == nil {
  121. break
  122. }
  123. temp = temp.next
  124. }
  125. // 2. 遍历链表
  126. for {
  127. fmt.Printf("[%d , %s , %s] => ", temp.no, temp.name, temp.nickname)
  128. temp = temp.pre
  129. if temp.pre == nil {
  130. break
  131. }
  132. }
  133. fmt.Println()
  134. }
  135. func main() {
  136. // 1. 创建头节点
  137. head := &HeroNode{}
  138. // 2. 创建 HeroNode
  139. hero1 := &HeroNode{
  140. no: 1,
  141. name: "luffy",
  142. nickname: "海贼王",
  143. }
  144. hero2 := &HeroNode{
  145. no: 2,
  146. name: "索隆",
  147. nickname: "大剑豪",
  148. }
  149. hero3 := &HeroNode{
  150. no: 3,
  151. name: "山治",
  152. nickname: "allblue",
  153. }
  154. hero4 := &HeroNode{
  155. no: 4,
  156. name: "甚平",
  157. nickname: "海侠",
  158. }
  159. insertNode02(head, hero1)
  160. insertNode02(head, hero3)
  161. insertNode02(head, hero2)
  162. insertNode02(head, hero4)
  163. fmt.Println("正序显示")
  164. showNode(head)
  165. fmt.Println("删除指定节点")
  166. delNode(head, 3)
  167. fmt.Println("逆序显示")
  168. showNode02(head)
  169. }
  170. /*
  171. 正序显示
  172. [1 , luffy , 海贼王] => [2 , 索隆 , 大剑豪] => [3 , 山治 , allblue] => [4 , 甚平 , 海侠] =>
  173. 删除指定节点
  174. 逆序显示
  175. [4 , 甚平 , 海侠] => [2 , 索隆 , 大剑豪] => [1 , luffy , 海贼王] =>
  176. */