返回

浅析 Go 语言下的常用排序算法,携手踏上算法之旅

后端







## Go 语言中的排序算法世界

在计算机科学中,排序算法是一种用于对一组数据进行排序的操作,使之遵循特定的顺序,例如从小到大或从大到小。排序算法在各个领域都有着广泛的应用,包括数据分析、机器学习、数据库查询和算法设计等。

Go 语言作为一门现代且流行的编程语言,提供了丰富的库和工具来帮助程序员轻松实现各种排序算法。本文将重点介绍几种在 Go 语言中常用的排序算法,包括插入排序、选择排序、冒泡排序、快速排序、堆排序、归并排序、基数排序和桶排序。

## 插入排序:简单高效的排序之选

插入排序是一种简单且易于理解的排序算法。它的工作原理类似于我们在现实生活中整理扑克牌的方式。我们从第一张牌开始,将其插入到前面已经排序好的牌堆中合适的位置,依次进行,直到将所有牌都插入完毕。

在 Go 语言中,插入排序的实现非常简单,代码如下:

```go
func insertionSort(arr []int) {
    for i := 1; i < len(arr); i++ {
        key := arr[i]
        j := i - 1
        for j >= 0 && arr[j] > key {
            arr[j+1] = arr[j]
            j--
        }
        arr[j+1] = key
    }
}

选择排序:逐个挑选最优元素

选择排序是一种通过逐个挑选最优元素来完成排序的算法。它从待排序的数据中选择出最小的元素,将其放置在第一个位置,然后继续选择出第二个最小的元素,将其放置在第二个位置,依此类推,直到所有元素都被排序完毕。

在 Go 语言中,选择排序的实现如下:

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

冒泡排序:简单直观的排序方法

冒泡排序是一种简单直观的排序算法。它的工作原理类似于我们在现实生活中通过摇晃一个装满乒乓球的容器来使乒乓球从小到大排列的方式。冒泡排序不断地比较相邻的两个元素,如果前一个元素大于后一个元素,则交换这两个元素的位置,依次进行,直到所有元素都被排序完毕。

在 Go 语言中,冒泡排序的实现如下:

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

快速排序:高效且经典的分治算法

快速排序是一种高效且经典的分治算法。它的工作原理是将待排序的数据分成较小的子集,然后递归地对每个子集进行排序,最后将排好序的子集合并成一个排好序的数据集。

在 Go 语言中,快速排序的实现如下:

func quickSort(arr []int) {
    if len(arr) <= 1 {
        return
    }
    pivot := arr[len(arr)/2]
    left, right := []int{}, []int{}
    for _, v := range arr {
        if v < pivot {
            left = append(left, v)
        } else if v > pivot {
            right = append(right, v)
        }
    }
    quickSort(left)
    quickSort(right)
    copy(arr, append(left, append([]int{pivot}, right...)...))
}

堆排序:基于堆结构的高效排序

堆排序是一种基于堆结构的高效排序算法。它将待排序的数据构建成一个堆,然后不断地从堆中取出最大的元素,依次将这些元素放入数组中,直到堆中没有元素为止。

在 Go 语言中,堆排序的实现如下:

func heapSort(arr []int) {
    n := len(arr)

    // 构建最大堆
    for i := n/2 - 1; i >= 0; i-- {
        heapify(arr, n, i)
    }

    // 将最大堆转换成排序数组
    for i := n - 1; i >= 0; i-- {
        arr[0], arr[i] = arr[i], arr[0]
        heapify(arr, i, 0)
    }
}

// 堆化函数
func heapify(arr []int, n, i int) {
    largest := i
    left := 2*i + 1
    right := 2*i + 2

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

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

归并排序:分治算法的典范

归并排序是一种分治算法的典范。它将待排序的数据分成较小的子集,然后递归地对每个子集进行排序,最后将排好序的子集合并成一个排好序的数据集。

在 Go 语言中,归并排序的实现如下:

func mergeSort(arr []int) {
    if len(arr) <= 1 {
        return
    }
    mid := len(arr) / 2
    left := arr[:mid]
    right := arr[mid:]
    mergeSort(left)
    mergeSort(right)
    merge(arr, left, right)
}

// 合并函数
func merge(arr []int, left, right []int) {
    i, j, k := 0, 0, 0
    for i < len(left) && j < len(right) {
        if left[i] < right[j] {
            arr[k] = left[i]
            i++
        } else {
            arr[k] = right[j]
            j++
        }
        k++
    }
    for i < len(left) {
        arr[k] = left[i]
        i++
        k++
    }
    for j < len(right) {
        arr[k] = right[j]
        j++
        k++
    }
}

基数排序:适用于整数排序的线性时间算法

基数排序是一种适用于整数排序的线性时间算法。它将待排序的数据按照个位、十位、百位等依次排序,最后将排好序的各个部分合并成一个排好序的数据集。

在 Go 语言中,基数排序的实现如下:

func radixSort(arr []int) {
    maxNum := arr[0]
    for _, v := range arr {
        if v > maxNum {
            maxNum = v
        }
    }
    exp := 1
    for maxNum/exp > 0 {
        countingSort(arr, exp)
        exp *= 10
    }
}

// 计数排序函数
func countingSort(arr []int, exp int) {
    n := len(arr)
    output := make([]int, n)
    count := make([]int, 10)
    for _, v := range arr {
        index := v / exp % 10