• 快速排序算法


    快速排序(QuickSort)
    划分的关键是要求出基准记录所在的位置pivotpos,编程时候的关键点

    快速排序:

    既然能把冒泡KO掉,马上就激起我们的兴趣,tnd快排咋这么快,一定要好好研究一下。

    首先上图:    

    从图中我们可以看到:

    left指针,right指针,base参照数。

    其实思想是蛮简单的,就是通过第一遍的遍历(让left和right指针重合)来找到数组的切割点。

    第一步:首先我们从数组的left位置取出该数(20)作为基准(base)参照物。

    第二步:从数组的right位置向前找,一直找到比(base)小的数,

                如果找到,将此数赋给left位置(也就是将10赋给20),

                此时数组为:10,40,50,10,60,

                left和right指针分别为前后的10。

    第三步:从数组的left位置向后找,一直找到比(base)大的数,

                 如果找到,将此数赋给right的位置(也就是40赋给10),

                 此时数组为:10,40,50,40,60,

                 left和right指针分别为前后的40。

    第四步:重复“第二,第三“步骤,直到left和right指针重合,

                 最后将(base)插入到40的位置,

                 此时数组值为: 10,20,50,40,60,至此完成一次排序。

    第五步:此时20已经潜入到数组的内部,20的左侧一组数都比20小,20的右侧作为一组数都比20大,

                以20为切入点对左右两边数按照"第一,第二,第三,第四"步骤进行,最终快排大功告成。

     快速排序具有最好的平均性能(average behavior),但最坏性能(worst case behavior)和插入排序

    相同,也是O(n^2)。比如一个序列5,4,3,2,1,要排为1,2,3,4,5。按照快速排序方法,每次只会有一个数据进入正确顺序,不能把数据分成大小相当的两份,很明显,排序的过程就成了一个歪脖子树,树的深度为n,那时间复杂度就成了O(n^2)。尽管如此,需要排序的情况几乎都是乱序的,自然性能就保证了。据书上的测试图来看,在数据量小于20的时候,插入排序具有最好的性能。当大于20时,快速排序具有最好的性能,归并(merge sort)和堆排序(heap sort)也望尘莫及,尽管复杂度都为nlog2(n)。
    1、算法思想

         快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

    (1) 分治法的基本思想
         分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

    (2)快速排序的基本思想
         设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
    ①分解: 
         在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
      注意:
         划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
         R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
                      其中low≤pivotpos≤high。
    ②求解: 
         通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

    ③组合: 
         因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

    实现代码如下:

    复制代码
     1 def parttion(v, left, right):
     2     key = v[left]
     3     low = left
     4     high = right
     5     while low < high:
     6         while (low < high) and (v[high] >= key):
     7             high -= 1
     8         v[low] = v[high]
     9         while (low < high) and (v[low] <= key):
    10             low += 1
    11         v[high] = v[low]
    12         v[low] = key
    13     return low
    14 def quicksort(v, left, right):
    15     if left < right:
    16         p = parttion(v, left, right)
    17         quicksort(v, left, p-1)
    18         quicksort(v, p+1, right)
    19     return v
    20 
    21 s = [6, 8, 1, 4, 3, 9, 5, 4, 11, 2, 2, 15, 6]
    22 print("before sort:",s)
    23 s1 = quicksort(s, left = 0, right = len(s) - 1)
    24 print("after sort:",s1)
    复制代码

    运行结果:

    before sort: [6, 8, 1, 4, 3, 9, 5, 4, 11, 2, 2, 15, 6]
    after sort: [1, 2, 2, 3, 4, 4, 5, 6, 6, 8, 9, 11, 15]
  • 相关阅读:
    美团容器平台架构及容器技术实践
    【人物志】美团首席科学家夏华夏:不断突破边界的程序人生
    Category 特性在 iOS 组件化中的应用与管控
    浅谈大型互联网企业入侵检测及防护策略
    【基本功】深入剖析Swift性能优化
    CAT 3.0 开源发布,支持多语言客户端及多项性能提升
    安装window下的redis,redis可视化管理工具(Redis Desktop Manager)安装,基础使用,实例化项目
    .Net Core Redis的使用
    焦点IT Redis安装与配置( Windows10 或Windows server)
    用VScode配置Python开发环境
  • 原文地址:https://www.cnblogs.com/zknublx/p/9035023.html
Copyright © 2020-2023  润新知