链表在内存中结构如下:
- 单链表插入末尾
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后一个,再删除