Go语言实现经典排序算法 | 青训营笔记

86 阅读3分钟

插入排序

插入排序是一种简单直观的排序算法。它的基本思想是将待排序的序列分成两部分,已排序和未排序部分。每次从未排序部分取出一个元素,插入到已排序部分的适当位置,使得已排序部分仍然有序。

以下是使用Go语言实现插入排序的代码:

goCopy code
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 = j - 1
        }
        arr[j+1] = key
    }
}

在这段代码中,我们使用了一个嵌套的循环。外层循环从第二个元素开始,逐个遍历待排序序列。内层循环将当前元素与已排序部分的元素进行比较,并将较大的元素后移,为当前元素找到合适的位置。

插入排序的时间复杂度为O(n^2),其中n是待排序序列的长度。虽然插入排序在小规模数据上表现良好,但对于大规模数据效率较低。

快速排序

快速排序是一种常用的排序算法,采用分治的思想。它的基本思想是通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都比另一部分小,然后再对这两部分分别进行排序,递归地进行这个过程,最终得到有序序列。

以下是使用Go语言实现快速排序的代码:

goCopy code
func quickSort(arr []int, low, high int) {
    if low < high {
        pivot := partition(arr, low, high)
        quickSort(arr, low, pivot-1)
        quickSort(arr, pivot+1, high)
    }
}

func partition(arr []int, low, high int) int {
    pivot := arr[high]
    i := low - 1
    for j := low; j < high; j++ {
        if arr[j] < pivot {
            i++
            arr[i], arr[j] = arr[j], arr[i]
        }
    }
    arr[i+1], arr[high] = arr[high], arr[i+1]
    return i + 1
}

在快速排序中,我们首先选择一个枢纽元素(一般为待排序序列的最后一个元素),然后通过划分操作将序列分成两部分。具体划分操作中,我们维护一个指针i,它指向已处理的元素的最后一个,通过与枢纽元素比较,将小于枢纽元素的元素交换到i的位置。最后,将枢纽元素放置在i+1的位置,完成一趟划分。

快速排序的时间复杂度为O(nlogn),其中n是待排序序列的长度。快速排序的性能通常优于其他排序算法,尤其在大规模数据的排序中表现出色。

堆排序

堆排序是一种基于二叉堆的排序算法。它利用堆的性质进行排序,其中堆是一种特殊的二叉树,满足堆序性质。在堆排序过程中,我们将待排序序列构建成一个最大堆(或最小堆),然后依次将堆顶元素与末尾元素交换,并调整堆,使得剩余序列仍满足堆序性质。

以下是使用Go语言实现堆排序的代码:

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

堆排序的关键在于构建堆和调整堆的过程。首先,我们从最后一个非叶子节点开始,向上构建最大堆。然后,将堆顶元素与最后一个元素交换,将最大元素放置在序列末尾。接着,调整剩余元素形成的堆,使其满足堆序性质。重复执行这个过程,直到整个序列有序。

堆排序的时间复杂度为O(nlogn),其中n是待排序序列的长度。堆排序具有较好的性能,并且不需要额外的存储空间。

总结与感想

利用Go语言实现插入排序、快速排序和堆排序,我们可以看到这些排序算法的不同思路和实现方式。插入排序是一种简单直观的排序算法,适用于小规模数据。快速排序是一种高效的排序算法,利用分治思想和划分操作快速将序列排序。堆排序则利用堆的特性进行排序,具有较好的性能。

通过实现这些排序算法,我们能够更好地理解它们的工作原理和时间复杂度。同时,使用Go语言编写算法也能够加深对该语言的理解和熟练度。在实际应用中,根据数据规模和要求,选择适合的排序算法可以提高程序的效率和性能。

总的来说,学习和实践排序算法是程序员的基本功之一。掌握常见的排序算法,能够更好地理解算法和数据结构的原理,为解决实际问题提供有力支持。同时,不断学习和探索更高效的排序算法也是提升自己的一个过程。