原理:
在序列中找一个基准数,然后,通过一定的次序调整(如交换位置或不断填坑的方式),使得这个基准数的位置前面的数都小于基准数,后面的数都大于这个基准数,那么,就找到了这个基准数的位置,然后,不断地递归这个过程。
算法步骤:
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}