快速排序

快速排序

概述

快速排序算法最早由图灵奖获得者Tony Hoare设计
快速排序算法被列为20实际十大算法之一
快速排序属于交换排序类,是通过不断比较和移动交换来实现的,快速排序的实现,比其他交换排序(比如冒泡排序),增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少总的比较次数和移动交换次数

快速排序算法

  • 快速排序(Qucik Sort)基本思想
    通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的
  • Go实现例子
    对数组[50,10,90,30,70,40,80,60,20]进行排序
package main

import "fmt"

type quick_sort struct {
    num_arr [9]int
}

func (q *quick_sort) QuickSort(low int, high int) {
    var pivot int
    if(low<high) {
        pivot = q.Partition(low, high)//将q *quick_sort一分为二 算出枢轴值pivot
        q.QuickSort(low, pivot-1)//对低子表递归排序
        q.QuickSort(pivot+1, high)//对高子表递归排序
    }
}

//交换子表(子数组)的记录,使枢轴记录到位,并返回其所在的位置
func (q *quick_sort) Partition(low int, high int) int {
    var pivotkey int
    var temp int//用于交换
    pivotkey = q.num_arr[low]//用子表的第一个记录做枢轴记录
    for {
        if (low>=high) {
            break
        }
        //从右边向中间扫描
        //高位值大于枢轴,继续循环,执行high--
        for {
            if (low >= high || q.num_arr[high] <= pivotkey) {
                break
            }
            high--
        }
        //高位数字小于枢轴,交换到低位
        temp = q.num_arr[low]
        q.num_arr[low] = q.num_arr[high]
        q.num_arr[high] = temp

        //从左边向中间扫描
        //低位小于枢轴,继续循环,执行low--
        for {
            if (low >= high || q.num_arr[low] >= pivotkey) {
                break
            }
            low++
        }
        //低位大于枢轴,交换到高位
        temp = q.num_arr[high]
        q.num_arr[high] = q.num_arr[low]
        q.num_arr[low] = temp

    }
    return low//返回枢轴的位置
}

func main()  {
    var q = quick_sort{}
    q.num_arr = [9]int{50,10,90,30,70,40,80,60,20}
    q.QuickSort(0, len(q.num_arr)-1)
    fmt.Printf("%v", q.num_arr)
}

运行后得到如下结果

go run QucikSort.go
[10 20 30 40 50 60 70 80 90]%

注释与说明
枢轴:Partition函数要做的,就是先选取数组中的一个关键字,比如选择第一个关键字50,然后想办法将它放到一个位置,使得它左边的值都比它小,右边的值都比它大,将这样的关键字称为枢轴
在经过第一调用q.Partition(0,8)之后,数组变成[20 10 40 30 50 70 80 60 90],并返回值4给pivot,表明50放在数组下标为4的位置
此时待排序数组变成两个小数组[20 10 40 30]和[70 80 60 90],对他们进行递归调用,直到顺序正确
执行过程描述
begin,low=0,high=9,将q.num_arr[0]=50赋值给pivotkey
q.num_arr[8]=20小于50,交换q.num_arr[0]与q.num_arr[8]的值,使得q.num_arr[0]=20,q.num_arr[8]=50
q.num_arr[0]=20小于50,执行low++,循环执行,直到q.num_arr[4]=90大于50,交换q.num_arr[2]与q.num_arr[8]的值,使得q.num_arr[2]=50,q.num_arr[8]=90
q.num_arr[8]=90大于50,执行high--,循环执行,直到q.num_arr[5]=40小于50,交换q.num_arr[5]与q.num_arr[4]的值,使得q.num_arr[2]=40,q.num_arr[5]=50...
...持续比较与交换值,直到low=high=4,退出循环,返回low的值4,进行递归调用,直到顺序正确

复杂度分析[TODO:分析过程待完善]

时间复杂度O(nlonn)
空间复杂度(logn)

优化

  • 优化选取枢轴
  • 优化必要的交换
  • 优化小数组时的排序方案
  • 优化递归操作

延伸

  • 排序分类
    根据排序过程中借助的主要操作,将内排序按下图进行分类

参考

大话数据结构

原文地址:https://www.cnblogs.com/biby/p/14855949.html