Go语言实现各类排序算法

排序算法是计算机科学中的一个重要概念,它是一种将一个无序的数列重新排列成有序的方法。常见的排序算法有:

选择排序(Selection Sort)

选择排序是一种简单直观的排序演算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,,再從剩餘未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以上步骤反复执行,直到所有数据元素均排序完毕。

Go 复制代码
package main

import "fmt"

func selectionSort(arr []int) {
    for i := 0; i < len(arr)-1; i++ {
        minIndex := i
        for j := i + 1; j < len(arr); j++ {
            if arr[j] < arr[minIndex] {
                minIndex = j
            }
        }
        arr[i], arr[minIndex] = arr[minIndex], arr[i]
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    selectionSort(arr)
    fmt.Println("Sorted array is:", arr)
}

冒泡排序(Bubble Sort):

最简单的排序算法,通过重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。

Go 复制代码
package main

import "fmt"

func bubbleSort(arr []int) {
    n := len(arr)
    for i := 0; i < n-1; i++ {
        for j := 0; j < n-i-1; j++ {
            if arr[j] > arr[j+1] {
                arr[j], arr[j+1] = arr[j+1], arr[j]
            }
        }
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    bubbleSort(arr)
    fmt.Println("Sorted array is:", arr)
}

插入排序(Insertion Sort):

插入排序是一种简单直观的排序演算法。通过构建有序序列,对未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

Go 复制代码
package main

import (
    "fmt"
)

func insertSort(arr []int) {
    n := len(arr)
    for i := 1; i < n; i++ {
        for j := i; j > 0 && arr[j] < arr[j-1]; j-- {
            arr[j], arr[j-1] = arr[j-1], arr[j]
        }
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    insertSort(arr)
    fmt.Println("Sorted array is:", arr)
}

希尔排序(Shell Sort):

希尔排序是一种插入排序的改进版本。希尔排序的基本思想是使数组中的元素像是在一个具有各种尺寸的篮子里进行排序。希尔排序通过设定一个步长,将数组分为若干个子序列,然后对这些子序列分别进行插入排序。当步长为1时,希尔排序就退化为插入排序。希尔排序的步长可以选择不同的值,通常选择2的幂次方,比如1,2,4,8,16,32等。

Go 复制代码
package main

import "fmt"

func shellSort(arr []int) {
    n := len(arr)
    gap := n / 2
    for gap > 0 {
        for i := gap; i < n; i++ {
            temp := arr[i]
            j := i
            for j >= gap && arr[j-gap] > temp {
                arr[j] = arr[j-gap]
                j -= gap
            }
            arr[j] = temp
        }
        gap /= 2
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    shellSort(arr)
    fmt.Println("Sorted array is:", arr)
}

归并排序(Merge Sort):

是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

Go 复制代码
package main

import (
    "fmt"
    "math/rand"
)

func merge(arr []int, l, m, r int) {
    n1 := m - l + 1
    n2 := r - m

    L := make([]int, n1)
    R := make([]int, n2)

    for i := 0; i < n1; i++ {
        L[i] = arr[l+i]
    }
    for j := 0; j < n2; j++ {
        R[j] = arr[m+1+j]
    }

    i := 0
    j := 0
    k := l
    for i < n1 && j < n2 {
        if L[i] <= R[j] {
            arr[k] = L[i]
            i++
        } else {
            arr[k] = R[j]
            j++
        }
        k++
    }

    for i < n1 {
        arr[k] = L[i]
        i++
        k++
    }

    for j < n2 {
        arr[k] = R[j]
        j++
        k++
    }
}

func mergeSort(arr []int, l, r int) {
    if l < r {
        m := (l + r) / 2
        mergeSort(arr, l, m)
        mergeSort(arr, m+1, r)
        merge(arr, l, m, r)
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    rand.Seed(42)
    for i := 0; i < len(arr); i++ {
        arr[i] = rand.Intn(100)
    }
    mergeSort(arr, 0, len(arr)-1)
    fmt.Println("Sorted array is:", arr)
}

快速排序(Quick Sort):

快速排序是一种高效的排序算法,基于分治法(Divide and Conquer)的一个策略。将要排序的数组分为两个子数组,一个包含相应的元素,一个包含其他的元素。

Go 复制代码
package main

import "fmt"

func quickSort(arr []int, left, right int) {
    if left < right {
        pivot := partition(arr, left, right)
        quickSort(arr, left, pivot-1)
        quickSort(arr, pivot+1, right)
    }
}

func partition(arr []int, left, right int) int {
    pivot := arr[right]
    i := left
    for j := left; j < right; j++ {
        if arr[j] <= pivot {
            arr[i], arr[j] = arr[j], arr[i]
            i++
        }
    }
    arr[i], arr[right] = arr[right], arr[i]
    return i
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    quickSort(arr, 0, len(arr)-1)
    fmt.Println("Sorted array is:", arr)
}

堆排序(Heap Sort):

是一种比较高效的选择排序,无论原址排序还是非原址排序都有其实现。

Go 复制代码
package main

import (
    "fmt"
)

func maxHeapify(arr []int, n int, i int) {
    largest := i
    l := 2*i + 1
    r := 2*i + 2

    if l < n && arr[l] > arr[largest] {
        largest = l
    }

    if r < n && arr[r] > arr[largest] {
        largest = r
    }

    if largest!= i {
        arr[i], arr[largest] = arr[largest], arr[i]
        maxHeapify(arr, n, largest)
    }
}

func heapSort(arr []int) {
    n := len(arr)
    for i := n/2 - 1; i >= 0; i-- {
        maxHeapify(arr, n, i)
    }

    for i := n - 1; i >= 0; i-- {
        arr[0], arr[i] = arr[i], arr[0]
        maxHeapify(arr, i, 0)
    }
}

func main() {
    arr := []int{64, 34, 25, 12, 22, 11, 90}
    heapSort(arr)
    fmt.Println("Sorted array is:", arr)
}

桶排序:

桶排序是计算机科学中的一种排序算法,工作原理是将要排序的元素划分到不同的桶,然后分别对每个桶中的元素进行排序,最后将每个桶中的元素合并成一个有序的序列。

Go 复制代码
package main

import (
    "fmt"
    "math"
)

func bucketSort(arr []float64) []float64 {
    var n int = len(arr)
    var maxValue = math.Ceil(max(arr))
    var size = math.Ceil((maxValue - min(arr)) / n)
    var buckets = make([][]float64, n)

    for i := 0; i < n; i++ {
        var index = int(math.Floor(arr[i]/size))
        buckets[index] = append(buckets[index], arr[i])
    }

    for i := 0; i < n; i++ {
        insertionSort(buckets[i])
    }

    var sortedArr []float64
    for i := 0; i < n; i++ {
        for j := 0; j < len(buckets[i]); j++ {
            sortedArr = append(sortedArr, buckets[i][j])
        }
    }

    return sortedArr
}

func insertionSort(arr []float64) []float64 {
    var n = len(arr)
    for i := 1; i < n; i++ {
        var key = arr[i]
        var j = i - 1
        for j >= 0 && arr[j] > key {
            arr[j+1] = arr[j]
            j = j - 1
        }
        arr[j+1] = key
    }
    return arr
}

func min(arr []float64) float64 {
    var min = arr[0]
    for _, value := range arr {
        if value < min {
            min = value
        }
    }
    return min
}

func max(arr []float64) float64 {
    var max = arr[0]
    for _, value := range arr {
        if value > max {
            max = value
        }
    }
    return max
}

func main() {
    var arr = []float64{0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434}
    var sortedArr = bucketSort(arr)
    fmt.Println("Sorted array:")
    for _, value := range sortedArr {
        fmt.Printf("%.3f ", value)
    }
}

计数排序:

计数排序是一种线性时间复杂度的排序算法,这种算法对输入的数据有一定的限制,如它们都是非负整数。计数排序是一种非比较排序算法,其核心思想是将输入的数据值转化为键存储在额外开辟的数组空间中。当输入数据是非负整数时,计数排序是一个线性时间排序算法。

Go 复制代码
package main

import "fmt"

func countSort(arr []int) []int {
    max := arr[0]
    min := arr[0]

    // 找到数组中的最大和最小值
    for _, v := range arr {
        if v > max {
            max = v
        }
        if v < min {
            min = v
        }
    }

    // 初始化计数数组
    count := make([]int, max-min+1)

    // 计算每个元素的数量
    for _, v := range arr {
        count[v-min]++
    }

    // 修改计数数组,使得每个元素的值表示该元素在数组中的位置
    for i := 1; i < len(count); i++ {
        count[i] += count[i-1]
    }

    // 创建一个结果数组,每个元素的位置由计数数组决定
    output := make([]int, len(arr))
    for i := len(arr) - 1; i >= 0; i-- {
        output[count[arr[i]-min]-1] = arr[i]
        count[arr[i]-min]--
    }

    return output
}

func main() {
    arr := []int{10, 20, 7, 8, 9, 1, 5}
    fmt.Println("Sorted array:")
    fmt.Println(countSort(arr))
}

基数排序:

基数排序是一种非比较整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。通常适用于对小范围整数的排序。将整个整数(例如名字或日期)中的每个数字或字母类似于排序每个单独的数字。

Go 复制代码
package main

import (
    "fmt"
    "math"
)

func countingSort(arr []int, exp int) {
    n := len(arr)
    output := make([]int, n)
    count := make([]int, 10)

    for i := 0; i < n; i++ {
        index := (arr[i] / exp) % 10
        count[index]++
    }

    for i := 1; i < 10; i++ {
        count[i] += count[i-1]
    }

    for i := n - 1; i >= 0; i-- {
        index := (arr[i] / exp) % 10
        output[count[index]-1] = arr[i]
        count[index]--
    }

    for i := 0; i < n; i++ {
        arr[i] = output[i]
    }
}

func radixsort(arr []int) {
    max := getMax(arr)

    for exp := 1; max/exp > 0; exp *= 10 {
        countingSort(arr, exp)
    }
}

func getMax(arr []int) int {
    max := math.Inf(-1)
    for _, num := range arr {
        if num > max {
            max = num
        }
    }
    return int(max)
}

func print(arr []int) {
    for _, num := range arr {
        fmt.Print(num, " ")
    }
    fmt.Println()
}

func main() {
    arr := []int{170, 45, 75, 90, 802, 24, 2, 66}
    radixsort(arr)
    print(arr)
}

斐波那契排序:

这是一个对冒泡排序的改进,通过引入斐波那契数列的概念,减少了比较的次数。工作原理是通过两层循环,外层循环控制整个排序过程,内层循环控制每一轮的排序。如果前一个元素大于后一个元素,就交换它们的位置。这样一轮比较下来,最大的元素就会移动到它应该在的位置上。

Go 复制代码
package main

import "fmt"

func swap(a *int, b *int) {
    *a, *b = *b, *a
}

func fbSort(arr []int) {
    n := len(arr)
    for i := 0; i < n-1; i++ {
        for j := 0; j < n-i-1; j++ {
            if arr[j] > arr[j+1] {
                swap(&arr[j], &arr[j+1])
            }
        }
    }
}

func main() {
    arr := []int{5, 8, 1, 3, 9, 6}
    fbSort(arr)
    fmt.Println("Sorted array:")
    for _, i := range arr {
        fmt.Println(i)
    }
}

哈夫曼排序:

哈夫曼排序是一种优先队列排序,它的基本思想是将待排序的序列看作是一棵完全二叉树,然后从上到下和从左到右进行排序。

Go 复制代码
package main

import (
    "fmt"
    "container/heap"
)

type Node struct {
    Value int
    Key   int
}

type PriorityQueue []*Node

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].Key < pq[j].Key
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
    item := x.(*Node)
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    *pq = old[0 : n-1]
    return item
}

func huffmanCodes(freq []int) {
    pq := make(PriorityQueue, 0)
    heap.Init(&pq)
    for i, val := range freq {
        if val > 0 {
            heap.Push(&pq, &Node{val, val, i})
        }
    }
    for pq.Len() > 1 {
        left := heap.Pop(&pq).(*Node)
        right := heap.Pop(&pq).(*Node)
        heap.Push(&pq, &Node{left.Key + right.Key, left.Key, left.Value})
        heap.Push(&pq, &Node{left.Key + right.Key, right.Key, right.Value})
    }
    fmt.Println(pq)
}

func main() {
    freq := []int{5, 9, 12, 13, 16, 45}
    huffmanCodes(freq)
}
相关推荐
爱吃生蚝的于勒11 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~15 分钟前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
lc寒曦37 分钟前
【VBA实战】用Excel制作排序算法动画
排序算法·excel·vba
王哈哈^_^40 分钟前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt
星沁城42 分钟前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵
脉牛杂德1 小时前
多项式加法——C语言
数据结构·c++·算法
legend_jz1 小时前
STL--哈希
c++·算法·哈希算法
kingmax542120081 小时前
初三数学,最优解问题
算法
一直学习永不止步1 小时前
LeetCode题练习与总结:赎金信--383
java·数据结构·算法·leetcode·字符串·哈希表·计数
小刘|2 小时前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法