快速排序
用于排序的最佳的实用选择,因其平均性能很好,期望运行时间O(nlog2^n),最坏情况运行时间为O(n^2).
1、快速排序
和合并排序一样,采取分治模式:
(1)分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A[q],而A[q+1..r]大于A[q],q在此划分过程中进行计算。
(2)解决:递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序
(3)合并:两个子数组都是原地排序的,因此合并不需要操作,整个数组就已经排好序
伪代码:
QUICKSORT(A,p,r)
if p<r then
q<—PARTITION(A,p,r)
QUICKSORT(A,p,q-1)
QUICKSORT(A,q+1,r)
最初调用QUICKSORT(A,1,A.length).
其中子程序PARTITION(A,p,r)代码如下,实现对子数组A[p..r]进行重排:
//对数组A[p,...,r]进行重排,使得A[p..q-1]中的每个元素都小于等于A[q],而A[q+1..r]大于A[q]
int partition(int a[],int p,int r){
int key=a[r];
int index=p-1;
int temp=0;
for(int i=p;i<=r-1;i++){
if(a[i]>key){
index++;
temp=a[i];
a[i]=a[index];
a[index]=temp;
}
}
temp=a[index+1];
a[index+1]=a[r];
a[r]=temp;
return index+1;
}
将A[r]=key作为参照数来进行对比,最后的结果是A[p..q-1]中的每个元素都小于等于key,而A[q+1..r]大于key,而A[q]最后和A[r]交换,并返回q。此子程序的运行时间为O(n),其中n=r-p+1.
2、快速排序的性能
快速排序的运行时间和划分是否对称有关,而后者又和选择了哪一个元素来进行划分比较有关。如果划分对称,渐近意义上,与合并算法(nlog2^n)一样快,不对称时,渐近意义上,和插入算法(n^2)一样慢。
(1)最坏情况
最坏划分是划分过程中产生的两个区域分别包含了n-1个元素和1个0元素。假设每次递归调用都出现了这种划分,划分的时间代价是O(n),递归树有n层,则算法的运行时间为O(n^2).递归表达式T(n)=T(n-1)+O(n).
(2)最好情况
最平衡的划分,两个子数组的大小都不可能大于n/2,递归式T(n)<=2T(n/2)+O(n),解为O(nlog2^n).由于每一层递归的划分都是两边对称的,因此,从渐进意义上,算法运行就更快了。
(3)平衡划分
平均情况和最佳运行时间很接近
任何一种按常数比例进行的划分都会产生深度为O(log2^n)的递归树,其中每一层的代价为O(n),因而,当按照常数比例划分时,总运行时间是O(nlog2^n).
3、快速排序的随机化版本
加入随机化部分,以便对于所有的输入,它均能获得较好的平均情况性能。随机化算法使得输入数组不相关,使最坏情况发生的可能性变小。
伪代码
RANDOMIZED-PARTITION(A,p,r)
i<—Random(p,r)
exchange A[r]<->A[i]
return PARTITION(A,p,r)
4、Hoare划分
将数组第一个元素作为对比元素,即主元,用两个指针分别从数组的首尾进行遍历,首指针找到第一个比主元大的元素,尾指针找到第一个比主元小(包括等于)的元素,将两个元素交换,循环进行此过程指导首尾指针相遇,最后的尾指针(包括尾指针)之前是比主元小(等于)的元素,尾指针后是比主元素大的元素,将尾指针位置的元素和主元素交换,并返回尾指针位置。
伪代码:
HOARE-PARTITION(A,p,r)
x<—A[p]
i<—p-1
j<—r+1
while TRUE
do repeat j<—j-1
until A[j]<=x
repeat i<—i+1
until A[i]>x
if i<j
then exchange A[i]<—>A[j]
else
A[p]<—>A[j]
return j
c代码
int hoare_partition(int a[],int p,int r){
int temp=0;
int key=a[p];
int i=p-1;
int j=r+1;
while(true){
do{
j--;
}while(a[j]>key);
do{
i++;
}while(a[i]<=key);
if(i<j){
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
else{
temp=a[p];
a[p]=a[j];
a[j]=temp;
return j;
}
}
}
此划分算法的运行时间为O(n),n=r-p+1.
分享到:
相关推荐
快速排序算法相关分析 快速排序算法是一种有效的排序算法,虽然算法在最坏的情况下运行时间为 O(n^2),但由于平均运行时间为 O(nlogn),并且在内存使用、程序实现复杂性上表现优秀,尤其是对快速排序算法进行随机化...
本篇文章将详细讨论几种常见的排序算法:选择排序、冒泡排序、插入排序、合并排序以及快速排序,分析它们的算法原理、时间效率,并通过经验分析验证理论分析的准确性。 **1. 选择排序(Selection Sort)** 选择排序...
压缩包中的"舍伍德——快速排序"文件很可能包含了以上提到的分析内容,详细解读这份报告可以帮助我们深入理解快速排序的原理和实践中的优化技巧。通过学习这份报告,无论是对算法的理解,还是在实际编程中应用快速...
(1)用随机快速排序的方法,对输入的数值以从大到小的顺序进行快速排序。 (2)对随机快速排序和冒泡排序这两种排序方法进行比较,测试其在不同数值大小的情况下算法运行的时间复杂度。 二、 实验要求 快速排序...
快速排序是一种高效的排序算法,在计算机科学和数学中被广泛研究。其基本原理是分治法策略,即将一组数据分为两个子序列并分别进行排序。快速排序期望的时间复杂度为O(nlogn),但在最坏的情况下,它的时间复杂度可...
### 快速排序知识点解析 #### 一、快速排序简介 快速排序是一种高效的排序算法,由英国计算机科学家托尼·霍尔...总之,快速排序是一种非常实用且高效的排序算法,掌握其原理及实现方式对于程序员来说非常重要。
快速排序和归并排序是两种常用的排序算法,它们在计算机科学中扮演着重要的角色,尤其在数据处理和算法效率分析方面。快速排序是由C.A.R. Hoare在1962年提出的,而归并排序则是一种基于分治策略的排序算法。 快速...
快速排序快速排序快速排序快速排序快速排序快速排序
快速排序、归并排序、基数排序等排序算法比较,比较时间性能,采用C++语言实现。。。
快速排序的时间复杂度可以通过对其递归树的分析来得到。假设我们有一个长度为n的数组,我们可以将其分成两个子数组,每个子数组的长度为n/2,于是我们可以得到一个递归公式: T(n) = 2T(n/2) + O(n) 通过解决这个...
快速排序是一种高效的排序算法,由英国计算机科学家C.A.R. Hoare在1960年提出。它的基本思想是分治策略,通过选取一个“基准”元素,将数组分为两个子数组,使得一个子数组的所有元素都小于或等于基准,另一个子数组...
算法设计分析课本中,根据快速排序算法而得来的程序。希望对大家有用~~
快速排序是一种高效的排序算法,由英国计算机科学家C.A.R. Hoare在1960年提出。它的基本思想是分治法,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按...
快速排序算法设计与分析 快速排序(Quicksort)是一种高效的排序算法,由美国计算机科学家Tony Hoare在1960年发明。该算法的时间复杂度平均为O(n log n),在实际应用中非常常用。 一、快速排序算法的基本思想 ...
### 快速排序性能分析:深入探讨 #### 引言 快速排序,作为一种经典的排序算法,自1960年由C.A.R. Hoare提出以来,因其高效的性能和优雅的逻辑,成为了计算机科学领域的基石之一。它基于分治策略,通过选取一个...
快速排序 实验数据:input.txt(共100个数据) ——要求按从小到大进行排序 将排好序的数据输出到output.txt文件中
在本文中,我们将对冒泡排序和快速排序的时间性能进行深入分析和比较。 冒泡排序是一种简单的排序算法,它的时间复杂度为O(n^2),其中n是要排序的元素个数。冒泡排序的基本思想是通过不断地比较和交换相邻元素来...
本实验旨在通过对两种经典排序算法——快速排序和归并排序的研究与实现,深入理解它们的基本原理、时间复杂度,并通过编程实践比较这两种算法在不同数据规模下的性能表现。 #### 二、快速排序 **1. 基本思想** ...
通过以上分析,我们可以看出这段代码实现了快速排序的基本逻辑,但在实际应用中还需要注意一些细节: - 基准值的选择会影响算法的效率。 - 在极端情况下,如已经排好序的数组,可能会导致快速排序退化为O(n^2)的时间...