zoukankan      html  css  js  c++  java
  • 快速排序

    快速排序

    概述

    快速排序算法最早由图灵奖获得者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)

    优化

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

    延伸

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

    参考

    大话数据结构

  • 相关阅读:
    HihoCoder 1638 : 小Hi的天平 (2-sat+并查集)
    阿里云安全肖力:云上数据安全体系建设的六要素
    MaxCompute客户端(odpscmd)在windows命令行下查询中文乱码问题处理实践
    序列化方案选型对比
    亚洲唯一,阿里云SLB位列Gartner全球网络负载均衡市场前五
    阿里云OSS同城冗余存储技术解析
    OSS跨同城3AZ重磅发布,构造全面数据保护体系
    阿里云OSS同城冗余存储正式商业化,提供云上同城容灾能力
    云原生应用 Kubernetes 监控与弹性实践
    GIAC2019 演讲精选 | 面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码
  • 原文地址:https://www.cnblogs.com/biby/p/14855949.html
Copyright © 2011-2022 走看看