快排
霍尔划分
思想:将最左边设为key值,int key = left; 设有两个指针,left 和 right ,
right从右往左找如果小于arr[key]的停下来,left从左往右找如果大于arr[key]停下来。注意必须是右边先走。
代码
int partion(int * arr , int left , int right)
{
int key = left;
while(left<right)
{
while(left<rightt && arr[right]>=arr[key])
{
right--;//找到小于arr[key]的时候停下来
}
while(left<right && arr[left]<=arr[key])
{
left++;//找到大于arr
}
//找到了,两个才可以交换
Swap(&arr[left],&arr[right]);
}
Swap(&arr[key],&arr[left]);//此时的left所指的下标必定小于key所指的
return left;
}
// 接着划分区间
void quickSort(int* arr , int left , int right)
{
if(left<=right) return;
int key = partion(arr,left , right);
quickSort(arr , left , key-1);
quickSort(arr , key+1 , right);
}
问题:为什么让 right 先走呢?
假设right先走 :
情况1, right遇到left停下来,停下的原因遇到比arr[key]小的
情况2,letf遇到right 停下来,由于是right先走,而right停下来的原因是遇到小于key的,此时left 来遇到 right , 即left==right
挖坑法
还是右边先走,遇到小于arr[key]的直接在key对应的位置赋值,然后左边再走,遇到比key大的,直接赋值给arr[key],
int partion(int * arr , int left , int right)
{
int hole = left;
int key = arr[left]
while(left<right)
{
while(left<rightt && arr[right]>=key)
{
right--;//找到小于arr[key]的时候停下来
}
arr[hole] = arr[right];
hole = right;
while(left<right && arr[left]<=key)
{
left++;//找到大于arr
}
arr[hole] = arr[left];
hole = left;
}
arr[left] = key;
return left;
}
// 接着划分区间
void quickSort(int* arr , int left , int right)
{
if(left<=right) return;
int key = partion(arr,left , right);
quickSort(arr , left , key-1);
quickSort(arr , key+1 , right);
}
前后指针法
思想:定一个前后指针,取左边为key,后指针先走,遇到大于的就往后走,遇到小的就停下来,此时前指针开始走,遇到小的继续走,遇到大的停下来.两个的值开始交换,然后 后指针继续往前走.接着重复这样的过程,最后出来的时候,要swap(prev,key)
int partion(int * arr , int left , int right)
{
int key = left;
int prev = left;//前指针
int cur = left+1;//后指针
while(cur<right)
{
if(arr[cur]>=arr[left])
{
cur++;
}else{
//先加加prev;第一个是key值,必须保持不变,key要和最后的prev交换
Swap(&arr[++prev],&arr[cur]);
cur++;
}
}
Swap(&arr[prev],&arr[key]);
return prev;
}
// 接着划分区间
void quickSort(int* arr , int left , int right)
{
if(left<=right) return;
int key = partion(arr,left , right);
quickSort(arr , left , key-1);
quickSort(arr , key+1 , right);
}