快速排序

1、快速排序

---- 快速排序(Quicksort)是对冒泡排序的一种改进,由C.A.R.Hoare在1962年提出。

它的基本思想是:通过“一趟排序”将要排序的数据分割成独立的两部分,其中左部分的所有数据都比右部分的所有数据都要,然后再按此方法

对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

2、算法过程

---- 设要排序的数组是A[0]......A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比

它大的数都放到它后面,这个过程称为一趟排序。

值得注意的是:快速排序不是一种稳定的排序算法,即多个相同的值的相对位置也许会在算法结束时产生变动。一趟快速排序的算法是:

----1)设置两个变量i,j,排序开始的时候:i=0,j=N-1;

----2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];注意该key值在整个过程中永远不变,始终是和key进行比较。

----3)从j开始由后向前搜索,找到第一个小于key的值A[j],并与A[i]交换;

----4)从i开始由前向后搜索,找到第一个大于key的值A[i],并与A[j]交换;

----5)重复第3、4步,直到i=j;

注意:3)4)步是在程序中没找到时候才j--和i++,直到找到为止。找到并交换的时候i和j指针位置不变。

#include <iostream>
using namespace std;
#define dim(x) (sizeof(x)/sizeof(x[0]))

void swap(int *x,int *y)
{
	int t = *x;
	*x = *y;
	*y = t;
}
//输入a[]:要排序的数组 nMin:第一个下标 nMax:最后一个下标
//输出:int-基准所在下标位置
//功能:分离数组并就地排序
int Partition(int a[],int nMin,int nMax)
{
	int key = a[nMin];
	int i = nMin;
	int j = nMax;
	do{
		//由后向前找到第一个比key小的元素,并与a[i]交换
		while(a[j]>=key && i<j)
		{
			j--;
		}
		if(i<j) swap(&a[i],&a[j]);
		while(a[i]<=key && i<j)
		{
			i++;
		}
		if(i<j) swap(&a[i],&a[j]);
	}while(i<j);
	return j;
}
void Quicksort(int a[],int nMin,int nMax)
{
	if(nMin>=nMax) return;
	if(nMin+1 == nMax) //若只有两个元素,直接比较
	{
		if(a[nMin]>a[nMax])
			swap(&a[nMin],&a[nMax]);
		return;
	}
	int j = Partition(a,nMin,nMax);
	Quicksort(a,nMin,j-1);
	Quicksort(a,j+1,nMax);
}

void Show(int a[],int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
}
int main()
{
	int a[]={49,38,65,97,76,13,27};
	Quicksort(a,0,dim(a)-1);
	Show(a,dim(a));
	system("pause");
	return 0;
}
输出:


快速排序的变种算法:随机化快排、平衡快排、外部快排

快速排序的最坏情况基于每次划分对主元的选择。基本的快速排序选取第一个元素作为主元。这样在数组已经有序的情况下,每次划分将得到最坏的

结果。一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元。这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入

数据,而是由于随机函数取值不佳。实际上,随机化快速排序得到理论最坏情况的可能性仅为O(1/(2^n))。

-- 所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。一位前辈做出了一个精辟的总结:“随机化快速排序可以满足一个

人一辈子的人品需求”。随机化快速排序的唯一缺点在于:一旦输入数据中有很多的相同数据,随机化的效果将直接减弱。对于极限情况,即对于n个

相同的数排序,随机化快速排序的时间复杂度将毫无疑问提高到O(n^2).一种解决方法是进行扫描,使没有交换的情况下主元保留在原位置。

-- 平衡快排(Balanced QuickSort):每次尽可能地选择一个能够代表中值的元素作为关键数据,然后遵循普通快排的原则进行比较、替换和递归。通

常来说,选择这个数据的方法是取开头、结尾、中间3个数,通过比较选出其中的中值。取这3个值的好处是在实际问题中,出现近似顺序数据或逆序数

据的概率较大,此时中间数据必然成为中值,也是事实上的近似中值。万一遇到正好中间大两边小的数据,取的值都接近最值。由于至少能将两部分分开,

实际效率也有2倍左右的增加。

-- 外部快排(External QuickSort):与普通快排不同的是,关键数据是一段buffer,首先将之前和之后的M/2个元素读入buffer并对该buffer中的这些元素

进行排序,然后从被排序数组的开头(或结尾)读入下一个元素,加入这个元素小于buffer中的最小元素,把它写到最开头的空位上;假如这个元素大于

buffer中最大的元素,则写到最后的空位上,否则把buffer中最大或者最小的元素写入数组,并把这个元素放在buffer里,保持最大值高于这些关键数据,

最小值低于这些关键数据,从而避免对已经有序的中间的数据进行重排。完成后,数组的中间空位必然空出,把这个buffer写入数组中间空位。然后递归的

对外部更小的部分,循环的对其他部分进行排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值