数组
快排的经典写法(挖坑)
func sort(nums []int) {
if len(nums) <= 1 {
return
}
pivot := nums[0]
i, j := 0, len(nums)-1
for i < j {
/*
为什么要先循环j,再循环i? 因为下面要 j>i ,才能继续循环,如果j先--了,下面就执行不了了
比如 i=2,j=3; 并且nums[i]<nums[j]; j在前,最后结果是, j=2,i=2; 如果是 i在前边,结果就是 j=3,i=3
*/
for ; i < j && nums[j] >= pivot; j-- {
}
// 为什么等于也可以?因为 nums[0]一定是等于 pivot 的,必须要等于,才能跳过
for ; i < j && nums[i] <= pivot; i++ {
}
nums[i], nums[j] = nums[j], nums[i]
}
nums[0], nums[i] = nums[i], nums[0]
sort(nums[:i])
sort(nums[i+1:])
}
func main() {
rand.New(rand.NewSource(time.Now().UnixNano()))
nums := make([]int, 10)
for i := range nums {
nums[i] = rand.Intn(100)
}
fmt.Println(nums)
sort(nums)
fmt.Println(nums)
}
k路并归
func main() {
a := [][]int{
{1, 12, 15, 24, 29},
{19, 25, 36, 38, 33},
{4, 9, 14, 16, 23},
}
ksort := func(numbs [][]int) []int {
n, m := len(a), len(a[0])
indexlist := make([]int, n)
ret := []int{}
for {
index := -1
minub := 1 << 32
for i := 0; i < n; i++ {
if indexlist[i] < m && numbs[i][indexlist[i]] < minub {
minub = numbs[i][indexlist[i]] //最小的数
index = i
}
}
if index == -1 {
break
}
indexlist[index]++
ret = append(ret, minub)
}
return ret
}
ret := ksort(a)
fmt.Println(ret)
}
堆排序
// 从 R[low]到R[high]的范围内对位置在low上的节点进行调整
// 没执行一直这个函数,就相当于位于 low 的这个点彻底调完,hight就是后来帮忙的。
func Sift(R []int, low, high int) {
i, j := low, 2*low // 树的节点,默认是从1开始的。
temp := R[i]
for j <= high {
if R[j] < R[j+1] && j < high { // 从左右节点中挑出来一个最大的
j++ // 变成右节点
}
if temp < R[j] {
R[i] = R[j] // 把j调整到双亲节点上
i = j // i是要放的节点 继续往下调整
j = i * 2
} else {
break
}
}
R[i] = temp // 把调整后的节点放在最终位置
}
func heapSort(R []int) {
// 调整顺序,先下后上,先右后左
n := len(R) - 1 // 因为序号要比次数-1,比如第5个节点,应该是 R[4]
for i := n / 2; i >= 1; i-- { // 叶子节点肯定都是堆,所以从 n/2 开始,应是从下到上,从右往左切换
Sift(R, i, n) // 循环调整完以后,最大的肯定在最上面。
}
for i := n; i >= 2; i-- {
R[1],R[i]=R[i],R[1]
Sift(R, 1, i-1) //把最大的和最后面的进行替换调整
}
}
func main() {
rand.Seed(time.Now().UnixNano())
r := make([]int, 20)
r[0] = 0
for i := 1; i < 20; i++ {
r[i] = rand.Intn(100)
}
fmt.Println(r)
heapSort(r)
fmt.Println(r)
}
双向链表
双向链表的插入和遍历输出
package main
import (
"fmt"
"math/rand"
"time"
)
type Node struct {
Data int
PrePoint *Node
NextPont *Node
}
type LinkList struct {
head *Node
current *Node
tail *Node
}
func main() {
rand.New(rand.NewSource(time.Now().UnixNano()))
datas := make([]int, 10)
for i := range 10 {
datas[i] = rand.Intn(100)
}
fmt.Println(datas)
linklists := new(LinkList)
for _, v := range datas {
node := new(Node)
node.Data = v
linklists.Insert(node)
}
linklists.ShowLinkList()
}
func (l *LinkList) Insert(node *Node) {
if l.head == nil {
l.head = node
l.current = node
l.tail = node
} else {
l.tail.NextPont = node
node.PrePoint = l.tail
l.tail = node // 只移动尾,头指针一直不动,中间的指针也一直不动
}
}
func (l *LinkList) ShowLinkList() {
for c := l.head; c != nil; c = c.NextPont {
fmt.Println(c.Data)
}
}
合并两个递增链表
package main
import (
"fmt"
"math/rand"
"time"
)
type Node struct {
Data int
PrePoint *Node
NextPont *Node
}
type LinkList struct {
head *Node
current *Node
tail *Node
}
func main() {
rand.New(rand.NewSource(time.Now().UnixNano()))
l1, l2 := new(LinkList), new(LinkList)
n1, n2 := 0, 0
for range 10 {
n1 += rand.Intn(10)
n2 += rand.Intn(10)
l1.Insert(&Node{Data: n1})
l2.Insert(&Node{Data: n2})
}
l1.ShowLinkList()
l2.ShowLinkList()
fmt.Println("===================================")
m := merge(l1, l2)
m.ShowLinkList()
}
func (l *LinkList) Insert(node *Node) {
if l.head == nil {
l.head = node
l.current = node
l.tail = node
} else {
l.tail.NextPont = node
node.PrePoint = l.tail
l.tail = node // 只移动尾,头指针一直不动,中间的指针也一直不动
}
}
func (l *LinkList) ShowLinkList() {
values := make([]int, 0)
for c := l.head; c != nil; c = c.NextPont {
values = append(values, c.Data)
}
fmt.Println(values)
}
func merge(l1, l2 *LinkList) (m *LinkList) {
m = new(LinkList)
c1, c2 := l1.head, l2.head
// 如果l1 和 l2 可以改变原有结构的话,其实可以用 m.Insert 的时候,可以直接插入 c1 或者 c2
for c1 != nil && c2 != nil {
// 这里是合并递增链表,所以排小的在前面
if c1.Data < c2.Data {
m.Insert(&Node{Data: c1.Data})
c1 = c1.NextPont
} else {
m.Insert(&Node{Data: c2.Data})
c2 = c2.NextPont
}
}
for c1 != nil {
m.Insert(&Node{Data: c1.Data})
c1 = c1.NextPont
}
for c2 != nil {
m.Insert(&Node{Data: c2.Data})
c2 = c2.NextPont
}
return m
}