- 雙鏈表最大的優勢就是可以雙向遍歷
package main
import "fmt"
type Node struct {
num int
name string
pre *Node
next *Node
}
// 末尾插入
func insert(head *Node, newNode *Node) {
tmp := head
for {
// 插入末尾,先連接左邊,後連接右邊
if tmp.next == nil {
tmp.next = newNode
newNode.pre = tmp
break
}
tmp = tmp.next
}
}
// 正向遍歷
func list(head *Node) {
tmp := head
if tmp.next == nil {
fmt.Printf("link is null")
}
for {
if tmp.next != nil {
// 第一個tmp代表head的下一個
fmt.Printf("[%d] = %s \n", tmp.next.num, tmp.next.name)
} else {
break
}
tmp = tmp.next
}
}
// 反向遍歷
func reverselist(head *Node) {
tmp := head
if tmp.next == nil {
fmt.Printf("link is null")
}
// 先將tmp指向鏈表末尾
for {
if tmp.next == nil {
break
}
tmp = tmp.next
}
for {
// 注意頭節點並不是空的,裏面還有mext和pre
if tmp.pre != nil {
fmt.Printf("[%d] = %s \n", tmp.num, tmp.name)
} else {
break
}
tmp = tmp.pre
}
}
func main() {
// head是隨機位置的指針
head := &Node{}
// 插入數據不需傳遞下一個node地址
node := &Node{
num: 1,
name: "amber",
}
node2 := &Node{
num: 2,
name: "alice",
}
node3 := &Node{
num: 3,
name: "necy",
}
node4 := &Node{
num: 4,
name: "bella",
}
insert(head, node)
insert(head, node2)
insert(head, node3)
insert(head, node4)
list(head)
fmt.Println()
reverselist(head)
}
輸出結果:
- 雙鏈表有序插入和刪除
package main
import "fmt"
type Node struct {
num int
name string
pre *Node
next *Node
}
func orderInsert(head *Node, newNode *Node) {
tmp := head
for {
// 必須放在前面,防止在末尾nil,被插在最後
if newNode.num == tmp.num {
fmt.Printf("node has already in link\n")
break
}
// 放在第二順位,當未找到插入最後
if tmp.next == nil {
tmp.next = newNode
newNode.pre = tmp
break
}
// 遍歷是從前往後,判斷條件tmp.next是保證在tmp後面插入前插入
if newNode.num < tmp.next.num {
// 先關聯右邊,再關聯左邊
newNode.next = tmp.next
newNode.pre = tmp
tmp.next.pre = newNode
tmp.next = newNode
break
}
tmp = tmp.next
}
}
func list(head *Node) {
tmp := head
if tmp.next == nil {
fmt.Printf("link is null")
}
for {
if tmp.next != nil {
// 第一個tmp代表head的下一個
fmt.Printf("[%d] = %s \n", tmp.next.num, tmp.next.name)
} else {
break
}
tmp = tmp.next
}
}
func delete(head *Node, num int) {
tmp := head
for {
if tmp == nil {
fmt.Printf("link is null")
break
}
// 注意這裏要找到tmp.next,因爲找到tmp是要刪除節點無法刪除
if tmp.num == num {
if tmp.next == nil {
tmp.pre.next = nil
break
} else {
tmp.next.pre = tmp.pre
tmp.pre.next = tmp.next
break
}
}
tmp = tmp.next
}
}
func main() {
// head是隨機位置的指針
head := &Node{}
// 插入數據不需傳遞下一個node地址
node := &Node{
num: 1,
name: "amber",
}
node2 := &Node{
num: 2,
name: "alice",
}
node3 := &Node{
num: 3,
name: "necy",
}
node4 := &Node{
num: 3,
name: "zoe",
}
orderInsert(head, node4)
orderInsert(head, node2)
orderInsert(head, node)
orderInsert(head, node3)
list(head)
fmt.Printf("****************\n")
delete(head, 2)
list(head)
}
輸出結果:
PS:這裏演示的是重複插入在最後的情況,所以要將重複判斷放在末尾插入之前
總結:
1、無論單鏈表還是雙鏈表插入一定定位在tmp和tmp.next之間
2、頭節點數據是空的,但不代表頭節點=nil
3、刪除和插入是一定要考慮刪除的恰好是最後的節點或者插入到最後的情況