快速排序

Posted by LuJiangBo on December 25, 2017

快速排序

快速排序又称划分交换排序,它也是分治排序的一种。它的平均运行时间是O(NlogN).

算法原理

利用分治法将一个待排序序列分为2个子序列,递归进行直到每个序列的元素为1,再向上合并已排好的序列。
步骤:

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

go语言代码实现


package main

import "log"

func main() {
	var arr = []int{1, 7, 3, 5, 0, 11, 65, 23, 55, 1, 23, 21, 65}
	l := len(arr)
	log.Println("原始序列:", arr)
	QuickSort(arr, 0, l-1)
	log.Println("排序后:", arr)
}

//QuickSort 排序函数
//s:起始位
//e:结束位
func QuickSort(arr []int, s, e int) {
	if s >= e {
		return
	}
	ck := arr[s]
	l := s
	r := e
	for l < r {
		for arr[r] > ck { //从右到左滑动,直到遇到第一个比基准点小的元素
			r--
		}
		Swep(arr, l, r)             //交换元素位置
		for l < r && arr[l] <= ck { //从左到右滑动,直到遇到第一个比基准点大的元素
			l++
		}
		Swep(arr, l, r)
		if r > s {
			r--
		}
	}
	//此时比基准点大的元素都在基准点右边
	//比基准点小的元素都在基准点左边
	QuickSort(arr, s, r)   //将基准点小的元素再执行快排
	QuickSort(arr, r+1, e) //将基准点大的元素再执行快排
}

//Swep 元素位置交换
func Swep(arr []int, x, y int) {
	if x == y {
		return
	}
	arr[y] = arr[x] + arr[y]
	arr[x] = arr[y] - arr[x]
	arr[y] = arr[y] - arr[x]
}

分析

快速排序也是递归排序,多变点在于基准点的选取,在上面的例子中始终用序列的第一个元素作为基准点,这在排序大部分已经排序好的序列时很可能会使时间复杂度上升到N^2.
因此一个好的基准点选取方法在快速排序中也很重要。