Golang排序详解

一、基本排序算法

Golang提供了多种基本排序算法,最常用的有冒泡排序、插入排序和选择排序。三种算法的主要区别在于排序的稳定性、时间复杂度和空间复杂度。

1. 冒泡排序

func BubbleSort(data sort.Interface) {
    for i := 0; i < data.Len()-1; i++ {
        for j := 0; j < data.Len()-1-i; j++ {
            if data.Less(j+1, j) {
                data.Swap(j, j+1)
            }
        }
    }
}

冒泡排序是一种基本的排序算法,它相邻的元素进行比较,如果满足条件则交换位置。该算法的时间复杂度为O(n^2)。

2. 插入排序

func InsertionSort(data sort.Interface) {
    for i := 1; i  0 && data.Less(j, j-1); j-- {
            data.Swap(j, j-1)
        }
    }
}

插入排序是一种比较稳定的排序算法,它将数组分为已排序和未排序两部分,每次从未排序的元素中选择一个插入到已排序的元素中。该算法的时间复杂度为O(n^2)。

3. 选择排序

func SelectionSort(data sort.Interface) {
    for i := 0; i < data.Len()-1; i++ {
        minIndex := i
        for j := i + 1; j < data.Len(); j++ {
            if data.Less(j, minIndex) {
                minIndex = j
            }
        }
        if minIndex != i {
            data.Swap(i, minIndex)
        }
    }
}

选择排序是一种比较简单的排序算法,它每次选择最小的元素放到已排序的元素中。该算法的时间复杂度为O(n^2)。

二、快速排序

快速排序是一种比较常用的排序算法,它的时间复杂度为O(nlogn)。该算法利用分治的思想,将一个大问题分成多个小问题解决,然后将小问题的结构合并起来。

func QuickSort(data sort.Interface) {
    quickSort(data, 0, data.Len()-1)
}

func quickSort(data sort.Interface, left, right int) {
    if left >= right {
        return
    }
    pivotIndex := partition(data, left, right)
    quickSort(data, left, pivotIndex-1)
    quickSort(data, pivotIndex+1, right)
}

func partition(data sort.Interface, left, right int) int {
    pivotIndex := left
    pivot := right
    for i := left; i < right; i++ {
        if data.Less(i, pivot) {
            data.Swap(i, pivotIndex)
            pivotIndex++
        }
    }
    data.Swap(pivotIndex, right)
    return pivotIndex
}

快速排序的主要思想是选择一个基准值(通常是数组的最后一个值),将数组分为两部分,一部分小于基准值,一部分大于基准值,然后按照同样的方式递归处理两部分的子数组,直到排序完成。

三、归并排序

归并排序是一种比较高效的排序算法,它的时间复杂度为O(nlogn)。该算法利用分治的思想,将一个大问题分成多个小问题解决,然后将小问题的结构合并起来。

func MergeSort(data sort.Interface) {
    mergeSort(data, 0, data.Len()-1)
}

func mergeSort(data sort.Interface, left, right int) {
    if left >= right {
        return
    }
    mid := (left + right) / 2
    mergeSort(data, left, mid)
    mergeSort(data, mid+1, right)
    merge(data, left, mid, right)
}

func merge(data sort.Interface, left, mid, right int) {
    tmp := make([]reflect.Value, right-left+1)
    i, j, k := left, mid+1, 0
    for i <= mid && j <= right {
        if data.Less(i, j) {
            tmp[k] = data.Index(i)
            i++
        } else {
            tmp[k] = data.Index(j)
            j++
        }
        k++
    }
    for i <= mid {
        tmp[k] = data.Index(i)
        k++
        i++
    }
    for j <= right {
        tmp[k] = data.Index(j)
        k++
        j++
    }
    for i, j := left, 0; i <= right; i, j = i+1, j+1 {
        data.Swap(i, reflect.Indirect(tmp[j]).Interface().(int))
    }
}

归并排序将数组分成两部分,分别排序,然后再将两个有序数组合并成一个有序数组。该算法需要额外的内存空间存储数组的拷贝,因此空间复杂度为O(n)。

四、堆排序

堆排序是一种比较常用的排序算法,它的时间复杂度为O(nlogn)。该算法利用堆的性质来实现排序。

func HeapSort(data sort.Interface) {
    heap := &Heap{data}
    heap.Init()
    for i := data.Len() - 1; i >= 0; i-- {
        heap.data.Swap(0, i)
        heap.size--
        heap.down(0)
    }
}

type Heap struct {
    data sort.Interface
    size int
}

func (h *Heap) Init() {
    h.size = h.data.Len()
    for i := h.size/2 - 1; i >= 0; i-- {
        h.down(i)
    }
}

func (h *Heap) down(root int) {
    for {
        left := root*2 + 1
        if left >= h.size {
            break
        }
        right := left + 1
        maxChildIndex := left
        if right < h.size && h.data.Less(left, right) {
            maxChildIndex = right
        }
        if h.data.Less(root, maxChildIndex) {
            h.data.Swap(root, maxChildIndex)
            root = maxChildIndex
        } else {
            break
        }
    }
}

堆是一种数据结构,它可以很方便地实现排序。堆排序分为两个阶段,第一阶段是建立一个最大堆,第二阶段是依次取出堆顶元素,并将剩余元素重新构建一个最大堆。

五、小结

本文介绍了Golang中的排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序。每种算法的时间复杂度和空间复杂度各有不同,开发者应该根据实际情况选择最合适的算法。

原创文章,作者:SAFO,如若转载,请注明出处:https://www.506064.com/n/131792.html

(0)
SAFOSAFO
上一篇 2024-10-03
下一篇 2024-10-03

相关推荐

发表回复

登录后才能评论