快速排序算法几种写法。
首先快排的思想是选取一个数来划分数组,这个数左边的数都小于等于它,右边的数都大于等于它。就这样递归的划分数组,最后达到快排的目的。
以下3种方法实现主要区别在于划分数组操作不一样,只要数组划分好了,后面操作都一样。
// 第一种方法,挖坑填坑方法。先选取数组第一个数作为参考数,然后分别设置两个指针i,j。i指向最左端,j指向最右端。首先把数组参考数所在位置挖掉作为当前坑,此时坑所在位置及指针i指向的位置,然后指针 j 开始遍历数组,直到遇到小于等于参考数的元素,将其挖出去填当前指针 i 指向的坑,此时更新新的坑,即指针 j 指向的坑,然后指针 i 向前遍历数组元素,直到找到大于等于参考数的元素,然后将其挖出去填指针j 指向的坑,依次反复,直到指针i与j相遇为止,最后把参考数填最后一个坑。这就是一趟排序结果。
#include<iostream>
using namespace std;
void quicksort(int a[], int left, int right){
int index = a[left];//choose the left data as a index data
int i = left; //从左边开始挖坑,i=left为第一个坑
int j = right;//指向排序数的两个指针
if (left >= right) //注意这里递归结束标志一定是划分数组没有元素为止,只有一个元素返回时不行,因为有可能越界情况出现
return ;
while (i < j){
while (a[j] > index && i < j)
--j;//从排序数组的右边开始遍历知道找到小于标志位的数
if (i < j)
a[i] = a[j];//第j个位置挖坑,挖出来东西填第i个坑
while (a[i] <= index && i < j)
++i;
if (i < j)
a[j] = a[i];// 第i个位置挖出东西填第j个位置坑
}
a[j] = index;
// 上面的实现选取左边第一个数为划分标志位,标志位左边的数都小于它,右边都大于等于它
quicksort(a,left,j-1);
quicksort(a,j+1,right);
}
int main(){
int a[]={9,2,3,7,4};
quicksort(a,0,4);
for (int i = 0; i < 5; ++i)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
第二种参考数归位方法是从数组左端开始遍历,选取数组最左端的元素作为参考数,并把中点指针指向参考数所在位置,(中点指针指的是其左端的数均小于参考数,其自身及其右端的数均大于等于参考数)如果遇到小于参考数的元素,就将其与中点指针指向的元素交换,并将中点指针向前一步,这样操作下去直到遍历完数组。
#include<iostream>
using namespace std;
void swap( int *a, int*b){
int c;
c=*a;
*a=*b;
*b=c;
}
void quicksort(int a[], int left, int right){
int temp = a[left];// 选取左边的数为划分数组的参考标准数
int j = left + 1;
int pivot = left; // pivot中间指针,pivot指针之前的数均小于参考数,pivot之后的数均大于等于参考数。
if (left < right){
while (j <= right){
if ( a[j] < temp){
swap(&a[j],&a[pivot]);
++pivot;
}
++j;
}
quicksort(a,left,pivot-1);
quicksort(a,pivot+1,right);
}
}
int main(){
int a[]={9,2,3,7,4};
quicksort(a,0,4);
for (int i = 0; i < 5; ++i)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
第一种和第二种方法主要区别就在比较次数不同,第二个相当于逐个冒泡遍历方法,每次都要需要将大数冒泡到后移,增加交换次数,但是挖坑填洞方法比较次数较少,例如9,3,2,7,4一趟排序的话,第一种只需要交换一次,即4与9交换,一趟下来结构为4,3,2,7,9;但是用第二种方法的话要把9往后冒泡,则交换4次,一趟结果为3,2,7,4,9.
第三种方法不用递归实现。
未完