一、快排的一次划分
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
template<class Type>
int Partition(Type *arr,int left,int right)
//快排的一次划分,返回下标i,以i将数据分为两部分
//一部分大于i,一部分小于i
{
int i=left;
int j=right;
Type tmp=arr[left];
while(i<j)
{
while(i<j && arr[j] > tmp)
{
--j;
if(i<j) arr[i]=arr[j];
}
while(i<j && arr[i] < tmp)
{
++i;
if(i<j) arr[j]=arr[i];
}
}
arr[i]=tmp;
return i;
}
二、快排的递归调用
template <typename Type> // 快排的递归调用
void PassQuick(Type *arr,int left,int right)
{
if(left <right)
{
Type mid=Partition(arr,left,right);
PassQuick(arr,left,mid-1);
PassQuick(Type *arr,mid+1,right);
}
}
三、快排的非递归调用
快排的非递归调用,可以利用栈和队列两种形式
template<class Type>
void QuickSort(Type *ar,int n)
{
SNicePassQuick(ar,0,n-1); //用栈,进行快排的非递归调用
QNicePassQuick(ar,0,n-1); //用队列,进行快排的非递归调用
}
- 利用栈
template <class Type> //用栈,进行快排的非递归调用
void SPassQuick(Type *arr,int left,int right)
{
if(left >= right) return ;
stack<int> s;
s.push(left);
s.push(right);
while(! s.empty())
{
right=s.top();s.pop();
left =s.top();s.pop();
Type mid=Partition(arr,left,right);
if(left < mid-1)
{
s.push(left);
s.push(mid -1);
}
if(mid+1 < right)
{
s.push(mid +1);
s.push(right);
}
}
}
- 利用队列
template<class Type> //用队列,进行快排的非递归调用
void QPassQuick(Type *arr,int left,int right)
{
if(left >=right) return ;
queue<int> q;
q.push(left);
q.push(right);
while(! s.empty() )
{
left =q.front(); q.pop();
right=q.front(); q.pop();
int mid = Partition(ar,left,right);
if(left < mid-1)
{
q.push(left);
q.push(mid-1);
}
if(mid+1 < right)
{
q.push(mid+1);
q.push(right);
}
}
}
四、快排的随机数法和三位取中法的优化
- 随机数法
template<class Type> //随机数法
int RandPartition(Type *ar,int left,int right)
{
srand(time(NULL));
int pos = rand() %(right - left + 1) + left;
swap(ar[left],ar[pos]);
return Partition(ar,left,right);
}
- 三位取中法
template<class Type> //三位取中法
int MidPartition(Type *ar,int left,int right)
{ // 23 89 45
int mid = (right - left + 1)/2 + left;
//ar[left] , ar[mid] , ar[right];
if(ar[mid] > ar[left] && ar[mid] < ar[right])
{
swap(ar[mid],ar[left]);
}else if(ar[right] > ar[mid] && ar[right] < ar[left])
{
swap(ar[right],ar[left]);
}
return Partition(ar,left,right);
}
这个三位取中法存在严重错误:两个if语句无法确定三个数排序的各种序列。可以考虑通过以下方法优化:
- 定义一个结构体:
struct MidNode
{
Type data;
int indax;
}
- STL库中的三位取中函数,Mid[3]={X,X,X} ------> mid[1]
五、快排一次划分:求第几小数
int Select_K_Min (int *ar,int n,int k)
{
if(ar == NULL || n < 1 || k<1 || k > n)
return -1;
else
return Select_K(ar,0,n-1,k);
}
int Select_K(int *ar,int left,int right,int k)
{
if(left == right && k == 1) return ar[left];
int pos = Partition(ar,left,right);
int j = pos - left + 1;
if(k <= j) return Select_K(ar,left,pos,k);
else return Select_K(ar,pos+1,right,k - j);
}
六、快排一次划分:最接近点对问题
int CPari(int *ar,int n)
{
if(ar == NULL || n < 1) return INT_MAX;
else
return cPari(ar,0,n-1);
}
int cPari(int *ar,int left,int right)
{
if(right - left <= 0) return INT_MAX;
int k = (right - left + 1)/2;
int pos = left + k - 1;
Select_K(ar,left,right,k);// 0 1 2 3 4 // 5 6 7 8 9
int d1 = CPari(ar,left,pos); //s1;
int d2 = CPari(ar,pos+1,right); //s2;
int maxs1 = MaxS1(ar,left,pos); //
int mins2 = MinS2(ar,pos+1,right);
return min(min(d1,d2),mins2 - maxs1);
}
int MaxS1(int *ar,int left,int right)
{
return ar[right];
}
int MinS2(int *ar,int left,int right)
{
int tmp = ar[left];
for(int i = left+1;i<=right;++i)
{
if(tmp > ar[i])
{
tmp = ar[i];
}
}
return tmp;
}
int main()
{
int ar[]={56,67,12,23,90,85,45,78,34,100,20,14,55,23};
int n = sizeof(ar)/sizeof(ar[0]);
int minlen = CPari(ar,n);
cout<<minlen<<endl;
cout<<endl;
return 0;
}