单链表算法

链表在内存中结构如下:

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后一个,再删除

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