鏈表在內存中結構如下:
- 單鏈表插入末尾
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後一個,再刪除