算法与数据结构(一)--快速排序

原理:

在序列中找一个基准数,然后,通过一定的次序调整(如交换位置或不断填坑的方式),使得这个基准数的位置前面的数都小于基准数,后面的数都大于这个基准数,那么,就找到了这个基准数的位置,然后,不断地递归这个过程。

算法步骤:

1.找一个基准数,一般为待排序序列左边的第一个,并且把这个位置作为第一个坑,并保存好这个数

2.从右往左找出第一个小于基准数的值,用以填上上面一个坑,而该值的位置成为一个新的坑

3.从左往右找出第一个大于等于基数的值,用以填上上面一个坑,而该值的位置成为一个新的坑

4.重复步骤2、3,直至带排列的序列为空,然后,将步骤1中保存的数放置到最后的那个坑

5.将以最后的坑的位置为分界,将左右两边的构成的序列进行递归。

代码如下:

#include <iostream>
using namespace std;
void QuickSort(int A[],int p,int r)
{   
	if(p<r)//递归调用停止条件
	{
		int x = A[p];
		int i = p;
		int j = r;	
		while(i<j)
		{
			while (i<j&&A[j]>=x)//从右往左找出第一个小于x的数
			{
				j--;
			}
			A[i] = A[j];
			i++;
			while (i<j&&A[i]<x)//从左往右找出第一个大于等于x的数
			{
				i++;
			}
			A[j] = A[i];
			j--;
			/*
			int tmp = A[i];
			A[i] = A[j];
			A[j] = tmp;
			i++;
			j--;*/
		}
		A[i] = x;
		//if(i>p+1)	//如果基数的位置和左边界相邻,左边停止递归
		QuickSort(A,p,i-1);
		//if(i<r-1)   //如果基数的位置和右边界相邻,右边停止递归
		QuickSort(A,i+1,r);		
	}
}

void main()
{
	int B[5]={9, 8 ,2 ,6 ,4};
	QuickSort(B,0,4);
	for(int i=0;i<5;i++)
	cout<<B[i]<<endl;
	system("pause");
}

上面的代码一开始以为是正确的,当时输入的数组是
{9, 8 ,2 ,6 ,4}

当输入的数组变成

{9, 8 ,2 ,6 ,2}
时,就会输出错误结果:

{8 ,2 ,6 ,2 ,9}
仔细检查程序才发现,原来是由于在填坑的时候,也就是在执行

			A[i] = A[j];
			i++;
的时候,并没有判断是否是真的找到了A[j]<x的元素,所以,当没有找到符合条件的元素,而到了i=j时,也会退出循环,此时,在去执行填坑和i++操作就不恰当了。所以,执行这两句的时候要加判断是否是真的找到了(即判断i<j是否成立)。

修改完成后的代码如下:

#include <iostream>
using namespace std;
void QuickSort(int A[],int p,int r)
{   
	if(p<r)//递归调用停止条件
	{
		int x = A[p];
		int i = p;
		int j = r;	
		while(i<j)
		{
			while (i<j&&A[j]>=x)//从右往左找出第一个小于x的数
			{
				j--;
			}
			if(i<j)
			{
			A[i] = A[j];
			i++;
			}
			while (i<j&&A[i]<x)//从左往右找出第一个大于等于x的数
			{
				i++;
			}
			if (i<j)
			{
				A[j] = A[i];
				j--;
			}

			/*
			int tmp = A[i];
			A[i] = A[j];
			A[j] = tmp;
			i++;
			j--;*/
		}
		A[i] = x;
		//if(i>p+1)	//如果基数的位置和左边界相邻,左边停止递归
		QuickSort(A,p,i-1);
		//if(i<r-1) //如果基数的位置和右边界相邻,右边停止递归
		QuickSort(A,i+1,r);		
	}
}

void main()
{
	int B[5]={9, 8 ,2,6 ,2};
	QuickSort(B,0,4);
	for(int i=0;i<5;i++)
	cout<<B[i]<<endl;
	system("pause");
}

终于可以输出正确的结果了:

{2, 2 ,6, 8 ,9}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值