SunJun/突破算法之-快速排序

Created Sun, 19 Aug 2018 01:30:00 +0800 Modified Tue, 27 Sep 2022 13:46:48 +0800
668 Words

算法原理

快速排序是图灵奖得主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地址