排序算法之快速排序

1、介绍

        快速排序(quick sort)是对冒泡排序的一种改进,它的主要思想是:通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列.


   快速排序是一种不稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动

2、示例

示例

假设用户输入了如下数组:

下标

0

1

2

3

4

5

数据

6

2

7

3

8

9

创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。我们取走了下标0的数据,于是,我们需要找到一个数字来替换他。由于我们要把所有比6小的数移动到左面,所以我们可以开始寻找比6小的数并从右往左找。别急,我们要按顺序找哦。不断递减j的值,我们发现下标3的数据比6小,于是把3移到下标0(实际是i指向的位置。代码中要用i,因为后面还会循环这个步骤,不用i的话第二次循环:

下标

0

1

2

3

4

5

数据

3

2

7

3

8

9

i=0 j=3 k=6

由于变量k已经储存了下标0的数据,所以我们可以放心的把下标0覆盖了。如此一来,下标3虽然有数据,但是相当于没有了,因为数据已经复制到别的地方了。于是我们再找一个数据来替换他。这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2是第一个比k大的,于是用下标2的数据7替换j指向的下标3的数据,数据状态变成下表:

下标

0

1

2

3

4

5

数据

3

2

7

7

8

9

i=2 j=3 k=6

重复上面的步骤,递减变量j。这时,我们发现ij“碰头了:他们都指向了下标2。于是,循环结束,把k填回下标2里,即得到结果。

填回k之后状态为:

下标

0

1

2

3

4

5

数据

3

2

6

7

8

9

如果ij没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。

注意:快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。(你可以想象一下ij是两个机器人,数据就是大小不一的石头,先取走i前面的石头留出回旋的空间,然后他们轮流分别挑选比k大和比k小的石头扔给对面,最后在他们中间把取走的那块石头放回去,于是比这块石头大的全扔给了j那一边,小的全扔给了i那一边。只是这次运气好,扔完一次刚好排整齐。)为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。


3、程序实现

#include<iostream>
#define SIZE 10
using namespace std;

void QuickSort(int arr[],int s,int e)
{
	if(s < e)
	{
		int i = s,j = e,x = arr[s];
		while(i < j)
		{
			//从右往左找第一个小于x的数
			while(i < j && arr[j] >= x)
				j--;
			if(i < j)
				arr[i++] = arr[j];

			//从左往右找第一个大于x的数
			while(i < j && arr[i] < x)
				i++;
			if(i < j)
				arr[j--] = arr[i];
		}
		arr[i] = x;
		//递归
		QuickSort(arr,s,i-1);
		QuickSort(arr,i+1,e);
	}
}

int main()
{
	int i;
	int number[SIZE] = {12,32,11,90,0,1,33,22,4,100};
	int len = sizeof(number)/sizeof(int);
	QuickSort(number,0,len-1);
	cout << "after sort:" <<endl;
	for(i=0;i<len;i++)
	{
		cout << number[i] <<endl;
	}
	system("pause");
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值