Golang的各种排序算法介绍

发布时间:2021-08-17 14:27:37 作者:chen
来源:亿速云 阅读:205

Golang的各种排序算法介绍

排序算法是计算机科学中最基本且重要的算法之一。在实际开发中,我们经常需要对数据进行排序,以便更高效地进行搜索、插入、删除等操作。Go语言(Golang)作为一门现代编程语言,提供了丰富的标准库和灵活的语言特性,使得实现各种排序算法变得简单而高效。本文将介绍几种常见的排序算法,并使用Go语言实现它们。

1. 冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的元素并交换它们的位置,直到整个列表有序为止。

算法步骤:

  1. 从列表的第一个元素开始,比较相邻的两个元素。
  2. 如果前一个元素大于后一个元素,则交换它们的位置。
  3. 继续遍历列表,直到没有需要交换的元素为止。

Go语言实现:

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]
            }
        }
    }
}

时间复杂度:

适用场景:

冒泡排序适用于小规模数据的排序,或者当数据已经基本有序时。

2. 选择排序(Selection Sort)

选择排序是一种简单直观的排序算法。它的工作原理是每次从未排序的部分中选择最小(或最大)的元素,放到已排序部分的末尾。

算法步骤:

  1. 在未排序的序列中找到最小(或最大)的元素。
  2. 将其放到已排序序列的末尾。
  3. 重复上述步骤,直到所有元素都排序完毕。

Go语言实现:

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

时间复杂度:

适用场景:

选择排序适用于小规模数据的排序,或者当内存空间有限时。

3. 插入排序(Insertion Sort)

插入排序是一种简单且高效的排序算法,特别适用于小规模数据或基本有序的数据。它的工作原理是将未排序的元素逐个插入到已排序部分的适当位置。

算法步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序。
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置。
  4. 重复步骤3,直到找到已排序的元素小于或等于新元素的位置。
  5. 将新元素插入到该位置后。
  6. 重复步骤2~5,直到所有元素都排序完毕。

Go语言实现:

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

时间复杂度:

适用场景:

插入排序适用于小规模数据的排序,或者当数据已经基本有序时。

4. 快速排序(Quick Sort)

快速排序是一种高效的排序算法,采用分治法(Divide and Conquer)策略。它的基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序。

算法步骤:

  1. 从数列中挑出一个元素,称为“基准”(pivot)。
  2. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

Go语言实现:

func QuickSort(arr []int) {
    if len(arr) <= 1 {
        return
    }
    pivot := arr[0]
    left, right := 1, len(arr)-1
    for left <= right {
        for left <= right && arr[left] <= pivot {
            left++
        }
        for left <= right && arr[right] >= pivot {
            right--
        }
        if left <= right {
            arr[left], arr[right] = arr[right], arr[left]
        }
    }
    arr[0], arr[right] = arr[right], arr[0]
    QuickSort(arr[:right])
    QuickSort(arr[right+1:])
}

时间复杂度:

适用场景:

快速排序适用于大规模数据的排序,尤其是在内存有限的情况下。

5. 归并排序(Merge Sort)

归并排序是一种稳定的排序算法,采用分治法策略。它的基本思想是将两个有序的子序列合并成一个有序的序列。

算法步骤:

  1. 将序列分成两个子序列,分别进行归并排序。
  2. 将两个有序的子序列合并成一个有序的序列。

Go语言实现:

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

func merge(left, right []int) []int {
    result := make([]int, 0, len(left)+len(right))
    i, j := 0, 0
    for i < len(left) && j < len(right) {
        if left[i] < right[j] {
            result = append(result, left[i])
            i++
        } else {
            result = append(result, right[j])
            j++
        }
    }
    result = append(result, left[i:]...)
    result = append(result, right[j:]...)
    return result
}

时间复杂度:

适用场景:

归并排序适用于大规模数据的排序,尤其是在需要稳定排序时。

6. 堆排序(Heap Sort)

堆排序是一种基于二叉堆数据结构的排序算法。它的基本思想是将待排序的序列构造成一个大顶堆(或小顶堆),然后将堆顶元素与末尾元素交换,再调整堆结构,重复此过程直到整个序列有序。

算法步骤:

  1. 将待排序的序列构造成一个大顶堆。
  2. 将堆顶元素与末尾元素交换,此时末尾元素为最大值。
  3. 将剩余的元素重新调整为大顶堆。
  4. 重复步骤2~3,直到整个序列有序。

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)
    }
}

时间复杂度:

适用场景:

堆排序适用于大规模数据的排序,尤其是在需要原地排序时。

7. 计数排序(Counting Sort)

计数排序是一种非比较排序算法,适用于整数排序。它的基本思想是统计每个元素出现的次数,然后根据统计结果将元素放回原数组。

算法步骤:

  1. 找出待排序数组中的最大值和最小值。
  2. 创建一个计数数组,大小为最大值与最小值的差加1。
  3. 统计每个元素出现的次数,存入计数数组。
  4. 根据计数数组,将元素放回原数组。

Go语言实现:

func CountingSort(arr []int) []int {
    if len(arr) == 0 {
        return arr
    }
    min, max := arr[0], arr[0]
    for _, v := range arr {
        if v < min {
            min = v
        }
        if v > max {
            max = v
        }
    }
    count := make([]int, max-min+1)
    for _, v := range arr {
        count[v-min]++
    }
    result := make([]int, 0, len(arr))
    for i, v := range count {
        for j := 0; j < v; j++ {
            result = append(result, i+min)
        }
    }
    return result
}

时间复杂度:

适用场景:

计数排序适用于整数排序,尤其是当数据范围不大时。

8. 基数排序(Radix Sort)

基数排序是一种非比较排序算法,适用于整数或字符串排序。它的基本思想是将整数按位数切割成不同的数字,然后按每个位数分别进行排序。

算法步骤:

  1. 找到数组中的最大值,确定最大位数。
  2. 从最低位开始,对数组进行计数排序。
  3. 重复步骤2,直到最高位排序完毕。

Go语言实现:

func RadixSort(arr []int) []int {
    if len(arr) == 0 {
        return arr
    }
    max := arr[0]
    for _, v := range arr {
        if v > max {
            max = v
        }
    }
    for exp := 1; max/exp > 0; exp *= 10 {
        countingSortByDigit(arr, exp)
    }
    return arr
}

func countingSortByDigit(arr []int, exp int) {
    n := len(arr)
    output := make([]int, n)
    count := make([]int, 10)
    for i := 0; i < n; i++ {
        digit := (arr[i] / exp) % 10
        count[digit]++
    }
    for i := 1; i < 10; i++ {
        count[i] += count[i-1]
    }
    for i := n - 1; i >= 0; i-- {
        digit := (arr[i] / exp) % 10
        output[count[digit]-1] = arr[i]
        count[digit]--
    }
    for i := 0; i < n; i++ {
        arr[i] = output[i]
    }
}

时间复杂度:

适用场景:

基数排序适用于整数或字符串排序,尤其是当数据范围不大且位数较少时。

9. 桶排序(Bucket Sort)

桶排序是一种非比较排序算法,适用于均匀分布的数据。它的基本思想是将数据分到有限数量的桶中,然后对每个桶中的数据进行排序,最后将各个桶中的数据合并。

算法步骤:

  1. 确定桶的数量和范围。
  2. 将数据分配到各个桶中。
  3. 对每个桶中的数据进行排序。
  4. 将各个桶中的数据合并。

Go语言实现:

func BucketSort(arr []int, bucketSize int) []int {
    if len(arr) == 0 {
        return arr
    }
    min, max := arr[0], arr[0]
    for _, v := range arr {
        if v < min {
            min = v
        }
        if v > max {
            max = v
        }
    }
    bucketCount := (max-min)/bucketSize + 1
    buckets := make([][]int, bucketCount)
    for _, v := range arr {
        index := (v - min) / bucketSize
        buckets[index] = append(buckets[index], v)
    }
    result := make([]int, 0, len(arr))
    for _, bucket := range buckets {
        if len(bucket) > 0 {
            InsertionSort(bucket)
            result = append(result, bucket...)
        }
    }
    return result
}

时间复杂度:

适用场景:

桶排序适用于均匀分布的数据,尤其是当数据范围不大且桶的数量适中时。

总结

本文介绍了Go语言中常见的几种排序算法,包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序、计数排序、基数排序和桶排序。每种排序算法都有其适用的场景和优缺点,选择合适的排序算法可以显著提高程序的性能。在实际开发中,我们可以根据数据的特点和需求选择合适的排序算法,或者结合多种排序算法来实现更高效的排序。

推荐阅读:
  1. golang的内存介绍
  2. Golang的接口介绍

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

golang

上一篇:常用的JS操作JSON方法有哪些

下一篇:Angular路由复用策略的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》