本文主要讲解快速排序的两种算法,递归与非递归,然后给出快速排序的优化算法,三路快速排序算法。
一、快速排序算法的递归实现
#include <iostream>
#include <algorithm>
//快速排序递归处理
using namespace std;
//处理一次排序是关键
template<class T>
int selectIndex(T arr[],int l,int r)
{
int num = arr[l];
int i = l+1;
int j = r;
while(i<=j)
{
if(arr[i]>num && arr[j]<=num)
swap(arr[i++],arr[j--]);
else if(arr[i]>num && arr[j]>num)
j--;
else if(arr[i]<=num && arr[j]<=num)
i++;
else
{
i++;
j--;
}
}
swap(arr[l],arr[j]);
return j;
}
// 该函数是利用双while,仔细体会
template<class T>
int selectIndex1(T arr[],int l,int r)
{
int num = arr[l];
int i = l+1;
int j = r;
while(true)
{
while(i<=r && arr[i]<num) i++;
while(j>=l+1 && arr[j]>num) j--;
if(i>j)
break;
swap(arr[i],arr[j]);
i++;
j--;
}
swap(arr[l],arr[j]);
return j;
}
template <class T>
void _quickSort(T arr[],int l,int r)
{
if(l>=r)
return;
int index = selectIndex1(arr,l,r);
_quickSort(arr,l,index-1);
_quickSort(arr,index+1,r);
}
template <class T>
void quickSort(T arr[],int n)
{
_quickSort(arr,0,n-1);
}
int main()
{
int a[] = {7,15,25,35,5,8,3,56,12,4,185,66,155,12};
int n = sizeof(a)/sizeof(int);
quickSort(a,n);
for(int i = 0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
其中一次排序函数尤为重要,我这里采用的是碰撞指针的思想,也可采用快慢指针思想,有兴趣的可以试试。
二、快速排序的非递归实现,肯定要用迭代实现,这里为了保存每次处理的边界,故要用到栈。
#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
template<class T>
int selectIndex(T arr[],int l,int r)
{
int num = arr[l];
int i = l+1;
int j = r;
while(i<=j)
{
if(arr[i]>num && arr[j]<=num)
swap(arr[i++],arr[j--]);
else if(arr[i]>num && arr[j]>num)
j--;
else if(arr[i]<=num && arr[j]<=num)
i++;
else
{
i++;
j--;
}
}
swap(arr[l],arr[j]);
return j;
}
template<class T>
void quickSort(T a[],int l,int r)
{
stack<T> s;
s.push(l);
s.push(r);
while(!s.empty())
{
int right = s.top();
s.pop();
int left = s.top();
s.pop();
int index = selectIndex(a,left,right);
if((index-1)>left)
{
s.push(left);
s.push(index-1);
}
if((index+1)<right)
{
s.push(index+1);
s.push(right);
}
}
}
int main()
{
float a[] = {7.5,15,25,35,5.6,8,3,56,12.55,4.33,185,66,155,12};
int n = sizeof(a)/sizeof(int);
quickSort(a,0,n-1);
for(int i = 0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
最后给出三路快排,所谓三路快排就是把小于轴等于轴大于轴分为三个区域,而上面的排序并没有分成三个区域,要么把等于归为大于等于里,反之,归为小于等于里,使用三路快排,把等于部分单独拿出。
#include <iostream>
#include <algorithm>
using namespace std;
template <class T>
void _quickSort(T arr[],int l,int r)
{
if(l>=r)
return;
int num = arr[l];
int lt = l;
int i = l+1;
int gt = r+1;
while(i<gt)
{
if(arr[i]<num)
{
swap(arr[lt+1],arr[i]);
i++;
lt++;
}
else if(arr[i] == num)
i++;
else{
swap(arr[i],arr[gt-1]);
gt--;
}
}
swap(arr[l],arr[lt]);
_quickSort(arr,l,lt-1);
_quickSort(arr,gt,r);
}
template <class T>
void quickSort(T arr[],int n)
{
_quickSort(arr,0,n-1);
}
int main()
{
int a[] = {7,15,25,35,5,8,3,56,12,4,185,66,155,12};
int n = sizeof(a)/sizeof(int);
quickSort(a,n);
for(int i = 0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
下标lt为小于轴的最后一个元素,i为当前要处理的元素,gt后面为大于轴的元素,维护下标尤为重要。