單鏈表算法

鏈表在內存中結構如下:

link

  • 單鏈表插入末尾
package main

import "fmt"

type Node struct {
	num  int
	name string
	next *Node
}

func insertNode(head *Node, newNode *Node) {
	tmp := head
	for {
		if tmp.next == nil {
			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 main() {
	// head是隨機位置的指針
	head := &Node{}

	// 插入數據不需傳遞下一個node地址
	node := &Node{
		num:  1,
		name: "amber",
	}
	node2 := &Node{
		num:  2,
		name: "alice",
	}

	insertNode(head, node)
	insertNode(head, node2)
	list(head)
}

輸出結果:
在這裏插入圖片描述

  • 單鏈表按順序插入
package main

import "fmt"

type Node struct {
	num  int
	name string
	next *Node
}

func orderInsert(head *Node, newNode *Node) {
	tmp := head
	for {
		//  必須寫在前面,因爲從頭開始遍歷,第一個遇到的就是空鏈表
		// 若放在後面,tmp.next.num會報錯
		if tmp.next == nil {
			tmp.next = newNode
			break
		}
		// 遍歷是從前往後,判斷條件tmp.next是保證在tmp後面插入前插入
		if newNode.num < tmp.next.num {
			// 先關聯右邊,再關聯左邊
			newNode.next = tmp.next
			tmp.next = newNode
			break
		}
		if newNode.num == tmp.num {
			fmt.Printf("node has already in link")
			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 main() {
	// head是隨機位置的指針
	head := &Node{}

	// 插入數據不需傳遞下一個node地址
	node := &Node{
		num:  1,
		name: "amber",
	}
	node2 := &Node{
		num:  2,
		name: "alice",
	}
	
	//注意這裏插入順序
	orderInsert(head, node2)
	orderInsert(head, node)
	list(head)
}

輸出結果:
在這裏插入圖片描述

  • 單鏈表刪除
package main

import "fmt"

type Node struct {
	num  int
	name string
	next *Node
}

func orderInsert(head *Node, newNode *Node) {
	tmp := head
	for {
		//  必須寫在前面,因爲從頭開始遍歷,第一個遇到的就是空鏈表
		// 若放在後面,tmp.next.num會報錯
		if tmp.next == nil {
			tmp.next = newNode
			break
		}
		// 遍歷是從前往後,判斷條件tmp.next是保證在tmp後面插入前插入
		if newNode.num < tmp.next.num {
			// 先關聯右邊,再關聯左邊
			newNode.next = tmp.next
			tmp.next = newNode
			break
		}
		if newNode.num == tmp.num {
			fmt.Printf("node has already in link")
			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.next.num == num {
			tmp.next = tmp.next.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",
	}

	orderInsert(head, node2)
	orderInsert(head, node)
	orderInsert(head, node3)
	list(head)

	fmt.Printf("****************\n")

	delete(head, 2)
	list(head)

}

輸出結果:
在這裏插入圖片描述

總結:
1、無論什麼操作,第一步一定是判斷頭節點
2、有序插入動作一定要在tmp後插入用tmp.next作比較,先關聯右邊,後關聯左邊
3、刪除動作一定要定位到tmp後一個,再刪除

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章