Golang算法模板-经典排序模板

36 阅读5分钟

sort.Slice

P1093 [NOIP2007 普及组] 奖学金

题目链接https://www.luogu.com.cn/problem/P1093

解法:从0开始

package main
​
import (
    "fmt"
    "sort"
)
​
type Student struct {
    id                     int
    score1, score2, score3 int
    sum                    int
}
​
func main() {
    var stu [305]Student
    var n int
    fmt.Scan(&n)
    for i := 0; i < n; i++ {
        fmt.Scan(&stu[i].score1, &stu[i].score2, &stu[i].score3)
        stu[i].sum = stu[i].score1 + stu[i].score2 + stu[i].score3
        stu[i].id = i + 1
    }
    //for i := 0; i < n; i++ {
    //  fmt.Printf("%d, %d, %d, %d, %d\n", stu[i].id, stu[i].score1, stu[i].score2, stu[i].score3, stu[i].sum)
    //}
    sort.Slice(stu[:n], func(i, j int) bool {
        if stu[i].sum != stu[j].sum {
            return stu[i].sum > stu[j].sum
        } else if stu[i].score1 != stu[j].score1 {
            return stu[i].score1 > stu[j].score1
        } else {
            return stu[i].id < stu[j].id
        }
    })
    for i := 0; i < 5; i++ {
        fmt.Printf("%d %d", stu[i].id, stu[i].sum)
        if i != 5-1 {
            fmt.Printf("\n")
        }
    }
}

冒泡排序

P1093 [NOIP2007 普及组] 奖学金

题目链接https://www.luogu.com.cn/problem/P1093

解法:从0开始

package main
​
import (
    "fmt"
)
​
type Student struct {
    id                     int
    score1, score2, score3 int
    sum                    int
}
​
func main() {
    var stu [305]Student
    var n int
    fmt.Scan(&n)
    for i := 0; i < n; i++ {
        fmt.Scan(&stu[i].score1, &stu[i].score2, &stu[i].score3)
        stu[i].sum = stu[i].score1 + stu[i].score2 + stu[i].score3
        stu[i].id = i + 1
    }
    //for i := 0; i < n; i++ {
    //  fmt.Printf("%d, %d, %d, %d, %d\n", stu[i].id, stu[i].score1, stu[i].score2, stu[i].score3, stu[i].sum)
    //}
    for i := 0; i < n-1; i++ { //遍历次数
        for j := 0; j < n-1-i; j++ { //位置
            if stu[j].sum != stu[j+1].sum {
                if stu[j].sum < stu[j+1].sum {
                    stu[j], stu[j+1] = stu[j+1], stu[j]
                }
            } else if stu[j].score1 != stu[j+1].score1 {
                if stu[j].score1 < stu[j+1].score1 {
                    stu[j], stu[j+1] = stu[j+1], stu[j]
                }
            } else if stu[j].id > stu[j+1].id {
                stu[j], stu[j+1] = stu[j+1], stu[j]
            }
        }
    }
    for i := 0; i < 5; i++ {
        fmt.Printf("%d %d", stu[i].id, stu[i].sum)
        if i != 5-1 {
            fmt.Printf("\n")
        }
    }
}

快速排序

partition1

下标从0开始,从小到大排序

func quickSort(arr []int, left, right int) {
    if left < right {
        pos := partition1(arr, left, right)
        quickSort(arr, left, pos-1)
        quickSort(arr, pos+1, right)
    }
}
func partition1(arr []int, left, right int) int {
    //选取最后一个元素作为基准pivot
    pivot := arr[right]
    pos := left
​
    //最后一个值就是基准,所以不用比较
    for i := left; i < right; i++ {
        if arr[i] <= pivot {
            arr[i], arr[pos] = arr[pos], arr[i] //swap(),
            pos += 1                            //pos之前(不包括pos,pos位置不确定)都是比pivot基准值小的,只有比基准值小的是否,才跟pos位置交换
        }
    }
    //把基准值换到中间
    arr[right], arr[pos] = arr[pos], arr[right]
    return pos
}
func main() {
    arr := []int{5, 8, 2, 1, 4, 3, 6, 2}
    quickSort(arr, 0, len(arr)-1)
    fmt.Println(arr)
}

partition2

下标从0开始,从小到大排序

​
func quickSort(arr []int, left, right int) {
    if left < right {
        pos := partition2(arr, left, right)
        quickSort(arr, left, pos-1)
        quickSort(arr, pos+1, right)
    }
}
func partition2(arr []int, left, right int) int {
    //选取最后一个元素作为基准pivot
    pivot := arr[right]
​
    l, r := left, right
    for l < r {
        //因为把pivot放在最后,所以先让l指针先走
        for l < r && arr[l] <= pivot {  //  注意有等于号
            l += 1
        }
        for l < r && arr[r] >= pivot {
            r -= 1
        }
        if l < r {
            arr[l], arr[r] = arr[r], arr[l]
        }
    }
    //把基准值换到中间
    arr[right], arr[l] = arr[l], arr[right]
    return l
}
func main() {
    arr := []int{5, 8, 2, 1, 4, 3, 6, 2}
    quickSort(arr, 0, len(arr)-1)
    fmt.Println(arr)
}

P1093 [NOIP2007 普及组] 奖学金

题目链接https://www.luogu.com.cn/problem/P1093

解法:从0开始

package main
​
import "fmt"
​
type Student struct {
    id                     int
    score1, score2, score3 int
    sum                    int
}
​
func quickSort(stu []Student, left, right int) {
    if left < right {
        pos := partition2(stu, left, right)
        quickSort(stu, left, pos-1)
        quickSort(stu, pos+1, right)
    }
}
​
//1:stu1>stu2; 0:stu1<stu2;
func compareStudent(stu1, stu2 Student) int {
    if stu1.sum != stu2.sum {
        if stu1.sum > stu2.sum {
            return 1
        } else {
            return 0
        }
    } else if stu1.score1 != stu2.score1 {
        if stu1.score1 > stu2.score1 {
            return 1
        } else {
            return 0
        }
    } else {
        if stu1.id < stu2.id {
            return 1
        } else {
            return 0
        }
    }
}
func partition2(stu []Student, left, right int) int {
    //fmt.Printf("%d, %d\n", left, right)
    //选取最后一个元素作为基准pivot
    pivot := stu[right]
​
    l, r := left, right
    for l < r {
        //因为把pivot放在最后,所以先让l指针先走
        for l < r && (compareStudent(stu[l], pivot) == 1 || stu[l].id == pivot.id) {
            l += 1
        }
        for l < r && (compareStudent(stu[r], pivot) == 0 || stu[r].id == pivot.id) {
            r -= 1
        }
        if l < r {
            stu[l], stu[r] = stu[r], stu[l]
        }
    }
    //把基准值换到中间
    stu[right], stu[l] = stu[l], stu[right]
    return l
}
func main() {
    var stu [305]Student
    var n int
    fmt.Scan(&n)
    for i := 0; i < n; i++ {
        fmt.Scan(&stu[i].score1, &stu[i].score2, &stu[i].score3)
        stu[i].sum = stu[i].score1 + stu[i].score2 + stu[i].score3
        stu[i].id = i + 1
    }
    //fmt.Println(stu[:n])
    quickSort(stu[:n], 0, n-1)
    for i := 0; i < 5; i++ {
        fmt.Printf("%d %d", stu[i].id, stu[i].sum)
        if i != 5-1 {
            fmt.Printf("\n")
        }
    }
}

归并排序

P1177 【模板】排序

https://www.luogu.com.cn/problem/P1177

从0开始

package main
​
import "fmt"
​
func Merge(arr []int, left, right, mid int) {
    arrTemp := make([]int, right-left+1)
    for k := left; k <= right; k++ {
        arrTemp[k-left] = arr[k]
    }
    i, j := left, mid+1
    for k := left; k <= right; k++ {
        if i > mid {
            arr[k] = arrTemp[j-left]
            j++
        } else if j > right {
            arr[k] = arrTemp[i-left]
            i++
        } else if arrTemp[i-left] > arrTemp[j-left] {
            arr[k] = arrTemp[j-left]
            j++
        } else {
            arr[k] = arrTemp[i-left]
            i++
        }
    }
}
func MergeSort(arr []int, left, right int) {
    if left >= right {
        return
    }
    mid := (left + right) / 2
    MergeSort(arr, left, mid) //[]
    MergeSort(arr, mid+1, right)
    Merge(arr, left, right, mid)
}
func main() {
    var n int
    fmt.Scan(&n)
    arr := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&arr[i])
    }
    MergeSort(arr, 0, n-1)
    for i := 0; i < n; i++ {
        fmt.Printf("%d", arr[i])
        if i != n-1 {
            fmt.Printf(" ")
        }
    }
}

堆排序

P1177 【模板】排序

https://www.luogu.com.cn/problem/P1177

从0开始

大根堆

package main
​
import "fmt"
​
func shiftdown(arr []int, n int, pos int) {
    for {
        lchild := pos*2 + 1
        rchild := pos*2 + 2
        idx := pos
        if lchild < n && arr[lchild] > arr[idx] {
            idx = lchild
        }
        if rchild < n && arr[rchild] > arr[idx] {
            idx = rchild
        }
        if idx == pos {
            break
        }
        arr[idx], arr[pos] = arr[pos], arr[idx] //swap
        pos = idx
    }
}
​
func HeapSort(arr []int) {
    //建立大根堆
    for i := len(arr)/2 - 1; i >= 0; i-- {
        shiftdown(arr, len(arr), i)
    }
    //交换arr[0]和arr[len(a)-1],然后把前面这段数组继续下沉保持大根堆,循环操作
    for i := len(arr) - 1; i >= 1; i-- {
        arr[0], arr[i] = arr[i], arr[0]
        shiftdown(arr, i, 0) // 注意这堆的长度要一点点缩小
    }
}
​
func main() {
    var n int
    fmt.Scan(&n)
    arr := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&arr[i])
    }
    HeapSort(arr)
    for i := 0; i < n; i++ {
        fmt.Printf("%d", arr[i])
        if i != n-1 {
            fmt.Printf(" ")
        }
    }
}

小根堆

package main
​
import "fmt"
​
func shiftdown(arr []int, n int, pos int) {
    for {
        lchild := pos*2 + 1
        rchild := pos*2 + 2
        idx := pos
        if lchild < n && arr[lchild] < arr[idx] {
            idx = lchild
        }
        if rchild < n && arr[rchild] < arr[idx] {
            idx = rchild
        }
        if idx == pos {
            break
        }
        arr[idx], arr[pos] = arr[pos], arr[idx] //swap
        pos = idx
    }
}
​
func HeapSort2(arr []int) {
    //建立小根堆
    for i := len(arr)/2 - 1; i >= 0; i-- {
        shiftdown(arr, len(arr), i)
    }
    //每次取出小根堆的根,就是最小值,和最后一个互换,然后缩小堆的大小,正序就是从大到小,倒序就是从小到大
    for i := 0; i < len(arr)-1; i++ {
        arr[0], arr[len(arr)-1-i] = arr[len(arr)-1-i], arr[0]
        shiftdown(arr, len(arr)-1-i, 0)
    }
​
}
​
func main() {
    var n int
    fmt.Scan(&n)
    arr := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&arr[i])
    }
    HeapSort2(arr)
    for i := n - 1; i >= 0; i-- {
        fmt.Printf("%d", arr[i])
        if i != 0 {
            fmt.Printf(" ")
        }
    }
}