突破算法之-快速排序

 · 2018-8-19 · 次阅读


算法原理

快速排序是图灵奖得主C.R.A. Hoare与1960年提出的一种
划分交换排序,它采用了一种分治策略。
分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

利用分治法可将快速排序的分为三步:

  • 在数据集之中,选择一个元素作为”基准”(pivot)
  • 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。这个操作称为分区 (partition) 操作,分区操作结束后,基准元素所处的位置就是最终排序后它的位置。
  • 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

Golang实现

package main

import "fmt"

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

    // http://jbcdn2.b0.upaiyun.com/2012/01/Visual-and-intuitive-feel-of-7-common-sorting-algorithms.gif
    array := []int{6, 7, 9, 3, 6, 8, 1, 9, 3}
    sort(array, 0, len(array)-1)
    fmt.Println(array)
}

func sort(array []int, left, right int) {
    if left > right {
        return
    }
    var storeIndex = partition(array, left, right)
    sort(array, left, storeIndex-1)
    sort(array, storeIndex+1, right)
}

func partition(array []int, left, right int) int {

    // 数组分区,左小右大
    var storeIndex = left
    // 直接选最右边的元素为基准元素
    var pivot = array[right]

    for i := left; i < right; i++ {
        if array[i] < pivot {
            if i != storeIndex {
                array[storeIndex], array[i] = array[i], array[storeIndex]
            }
            // 交换位置后,storeIndex 自增 1,代表下一个可能要交换的位置
            storeIndex++
        }
    }

    // 将基准元素放置到最后的正确位置上
    array[right], array[storeIndex] = array[storeIndex], array[right]
    return storeIndex
}

github地址