快速划分是不稳定的,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列,也可以非递归进行,两个方法依次讲解。
快速排序 的一次划分 时间复杂度O(n)空间复杂度O(1)
int Partition(int *arr,int low,int high)//O(n),O(1) //*******
{
int tmp = arr[low];//基准
while(low < high)
{
while(low<high && arr[high]>=tmp)
{
high--;
}
arr[low] = arr[high];
while(low<high && arr[low]<=tmp)
{
low++;
}
arr[high] = arr[low];
}
arr[low] = tmp;//low==high
return low;
}
1.递归的快速排序
static void Quick(int*arr,int low,int high)
{
int par = Partition(arr,low,high);
if(low+1 < par)//左边至少两个数据
{
Quick(arr,low,par-1);
}
if(par+1 < high)//右边至少两个数据
{
Quick(arr,par+1,high);
}
}
2.非递归的快速排序
非递归的快速排序需要引入栈来实现,这里建一个普通的顺序栈即可,引入头文件(栈的声明),再写一个栈的实现文件
void QuickSort(int *arr,int len)//O(n),O(logn),不稳定
{
SeqStack s;
InitStack(&s);
int low = 0;
int high = len-1;
int par = Partition(arr,low,high);
if(low+1 < par)
{
Push(&s,low);
Push(&s,par-1);
}
if(par+1 < high)
{
Push(&s,par+1);
Push(&s,high);
}
while(!IsEmpty(&s))
{
Pop(&s,&high);
Pop(&s,&low);//low=par+1;
par = Partition(arr,low,high);//找右边的基准位置
if(low+1 < par)
{
Push(&s,low);
Push(&s,par-1);
}
if(par+1 < high)
{
Push(&s,par+1);
Push(&s,high);
}
}
//先把基准右边的数据快排有序,然后在排左边的,利用后进先出的栈特性给low和high赋值来实现基准的定位
Destroy(&s);
}