排序算法(五)——快速排序

基本思想

快速排序也是基于分治算法得。步骤如下:

(1)选择一个基准元素,通常选择第一个元素或者最后一个元素;

(2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值比基准值大;

(3)此时基准元素在其排好序后的正确位置;

(4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。

上图中,演示的是第一轮快速排序的过程,首先将第一个元素选为基准点,从右端第一个元素开始扫描,找到第一个比57小的元素(19)时停止,两者交换位置,然后从左端开始扫描,找到第一个比57的元素(68)时停止,两者交换位置,周而复始,直到57找不到可交换的元素为止,至此一轮快速排序结束。

这时,比57小的元素都在左边,比57大的元素都在右边,分别对两边的数组段继续进行快速排序,依次类推,最终使整个数组有序。

java实现

//快速排序
      public void quikSort(){
             recursiveQuikSort(0,array.length-1);
      }

      /**
       * 递归的快速排序
       *@param low  数组的最小下标
       *@param high  数组的最大下标
       */
      private void recursiveQuikSort(int low,int high){
             if(low>=high){
                    return;
             }else{
                    int pivot = array[low];  //以第一个元素为基准
                    int partition =partition(low,high,pivot);  //对数组进行划分,比pivot小的元素在低位段,比pivot大的元素在高位段

                    display(); 

                    recursiveQuikSort(low,partition-1);  //对划分后的低位段进行快速排序
                    recursiveQuikSort(partition+1,high);  //对划分后的高位段进行快速排序
             }
      }

      /**
       * 以pivot为基准对下标low到high的数组进行划分
       *@param low 数组段的最小下标
       *@param high 数组段的最大下标
       *@param pivot 划分的基准元素
       *@return 划分完成后基准元素所在位置的下标
       */
      private int partition(int low,int high,int pivot){

             while(low<high){

                    while(low<high &&array[high]>=pivot){  //从右端开始扫描,定位到第一个比pivot小的元素
                           high--;
                    }
                    swap(low,high);

                    while(low<high &&array[low]<=pivot){  //从左端开始扫描,定位到第一个比pivot大的元素
                           low++;
                    }
                    swap(low,high);

             }
             return low;

      }
      /**
       * 交换数组中两个元素的数据
       *@param low 欲交换元素的低位下标
       *@param high 欲交换元素的高位下标
       */
      private void swap(int low,int high){
             int temp = array[high];
             array[high] = array[low];
             array[low] = temp;
      }

算法分析

在归并排序中,我们详细推算了时间复杂度,快速排序与归并排序一样采取了分治算法,它的时间复杂度也是O(N*log2N)。

对于分治算法一般都是如此,用递归的方法把数据项分为两组,然后调用自身来分别处理每一组数据。算法实际上是以2为底,运行时间与N*log2N成正比

对于快速排序来说,最理想的状态是随机分布的数据,即我们任意选定的枢纽处于中间位置,有一半元素小于它,有一半元素大于它。当数据时由小到大排列或者由大到小排列时,快速排序的效率最低,时间复杂度扩大为O(N2)

选定第一个元素为枢纽实现起来确实很简单,但是当它为最大值或最小值时,快速排序的效率会严重降低。假如选中的元素为数组的中值,自然是最好的选择,但是却要遍历整个数组来确定中值,这个过程可能比排序花费的时间还长,得不偿失。折衷的方法是找到数组中的第一个、最后一个以及处于中间位置的元素,选出三者的中值作为枢纽,既避免了枢纽是最值的情况,也不会像在全部元素中寻找中值那样费时间。这种方法被称为“三项取中法”(median-of-three)。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 23:02:46

排序算法(五)——快速排序的相关文章

排序算法 之 快速排序

快速排序是基于分治思想的一种排序算法,就像该方法的名字一样,速度比较快,所以叫做快速排序:它的平均时间复杂度为O(N*logN),最坏时间复杂度为O(n2),由于快速排序在序列元素数量多的时候速度比较快,所以很多语言内置的排序方法也是用快速排序实现的.快速排序也有很多优化的版本,比如在排序时基数的选择等等-下面就说一下一般的快速排序的实现. 基本思想: 快速排序的基本思想就是,先从待排序的序列中任选一个元素作为基数,然后将序列中的其他小于基数的元素放在基数的左边,大于或等于基数的元素放在基数的右

常用排序算法之——快速排序(C语言+VC6.0平台)

经典排序算法中快速排序具有较好的效率,但其实现思路相对较难理解. #include<stdio.h> int partition(int num[],int low,int high) //以key为基准 将待排数列“高”.“低 ”两部分,“高”部分的所有数据比key大,“低”部分的数据都比key小 { int left,right,key; left=low;right=high;key=num[low]; while(left<right) { while(left<right

常用排序算法之——快速排序

快速排序的原理: 首先找一个标兵值,等于某一个元素值:遍历数组,将数组分为小于标兵值和大于标兵值的两部分:然后分别对两个部分采用快速排序,递归. 分开数组时,维持一个指针,指向已找到小部分的最后一个元素:一个指针用于遍历. 不稳定排序算法.当数组已经有序时,时间复杂度最差,为O(N2),平均.最优情况下都为O(N lgN). 代码如下: 1 #include <iostream> 2 using namespace std; 3 4 template<typename T> 5 v

排序算法系列——快速排序

记录学习点滴 快速排序算法是一种很有趣的算法,短小精悍,性能强劲,对于大部分情况都可以胜任,但对极端环境难以应付. 快速排序我理解为:这是一个“以自我为中心的”+“分治法”思想的算法. 分治法不必多说,化繁为简,那就是逐个击破. 那什么是“以自我为中心”?顾名思义,就是每次都一个“我”,每个人都要围绕“我”行事,比“我”小的都去左边站着,比“我”他大的都去右边站着,而且“我”不去关心每一边都有谁,反正你没“我”大或者小就行.一旦“我”落位了妥帖了,“我”就不动了.然后再在左右两边分别产生新“我”

排序算法之快速排序Java实现

排序算法之快速排序 舞蹈演示排序: 冒泡排序: http://t.cn/hrf58M 希尔排序:http://t.cn/hrosvb  选择排序:http://t.cn/hros6e  插入排序:http://t.cn/hros0W  快速排序:http://t.cn/ScTA1d  归并排序:http://t.cn/Sc1cGZ 快速排序是一个就地排序,分而治之,大规模递归的算法.从本质上来说,它是归并排序的就地版本. 1.快速排序可以由下面四步组成:(1) 如果不多于1个数据,直接返回.(2

经典排序算法之快速排序(C语言版)

快速排序是一种很常用的排序算法. /*  * 快速排序(伪算法) 2016-04-20 23:34:16  * 1.先找到第一个元素的最终位置  * 2.对第一个元素的最终位置之前的元素,进行快速排序.  * 3.对第一个元素的最终位置之后的元素,进行快速排序.  * */ extern void QuickSort(int a[],int low,int high);//第二个参数表示第一个元素的下标,第三个参数表示最后一个元素的下标 extern int FindPos(int a[], i

排序算法之快速排序的随机化版本

4.3 快速排序的随机化版本 这种方法并不是一种全新的排序算法,而是在快速排序的基础上加入随机化的因素,因素,因而仍然将其作为第四种方法(快速排序)的一种补充. 为什么要提出快速排序的随机化版本,主要是对于快速排序法其划分情况的好坏会直接影响排序的效率,而且,快速排序的平均性能较好,所以,加入随机化成分,可以使该算法对于所有输入均能获得较好的平均情况性能. 针对加入随机化的环节,选取的是选取主元的环节,因为主元的选取直接影响快速排序算法的数组划分. C代码实现为: #include <stdio

排序算法之快速排序(Quicksort)解析

一.快速排序算法的优点,为什么称之为快排? Quicksort是对归并排序算法的优化,继承了归并排序的优点,同样应用了分治思想. 所谓的分治思想就是对一个问题“分而治之”,用分治思想来解决问题需要两个步骤: 1.如何“分”?(如何缩小问题的规模) 2.如何“治”?(如何解决子问题) 快排的前身是归并,而正是因为归并存在不可忽视的缺点,才产生了快排.归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的.针对这一点,快速排序提出了新的思路:把更多的时

Python实现排序算法之快速排序

Python实现排序算法:快速排序.冒泡排序.插入排序.选择排序.堆排序.归并排序和希尔排序 Python实现快速排序 原理 首先选取任意一个数据(通常选取数组的第一个数)作为关键数据,然后将所有比它小的放到它前面,所有比它大的放到它后面,这个过程称为一趟快速排序 快速排序原理图如下: 实现 #coding=utf-8 #python实现快速排序 def quick_sort(li,start,end): if start < end: flag = li[start] print(flag)

我的Java开发学习之旅------&gt;Java经典排序算法之快速排序

一.算法思想 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). (1) 分治法的基本思想 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题.递归地解这些子问题,然后将这些子问题的解组合为原问题的解. (2)快速排序的基本思想 设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为: ①分解: 在R[low..high]中任选一