基本思想:
快排也是一种分治的思想.
- 从一个数组中选择一个数作为基准值(基准值一般为数组的最后一个元素或者第一个元素).
- 遍历数组,如果大于基准值的放在基准值的右边,小于基准值的放在基准值的左边.
- 对左右两个部分再执行第二步,直至每个区间只有一个元素为止.
方法1:交换法
遍历数组,找到第一个大于基准值的元素停下来;然后从数组的后面从前遍历,找到第一个小于基准值的元素停下来;然后交换找到的两个值….
图解如下:
代码如下:
//交换法
int Partition(int arr[],int left,int right)
{
int end = right - 1;
int key = end;
while(left < end)
{
//找到左边第一个大于基准值的元素
while(arr[left] <= arr[key] && left < end)
{
++left;
}
//找到右边第一个小于基准值的元素
while(arr[end] >= arr[key] && left < end)
{
--end;
}
if(left < end)
{
swap(&arr[left],&arr[end]);
}
}
swap(&arr[left],&arr[key]);
return left;
}
void _QuickSort(int arr[],int start,int end)
{
if(end - start < 1)
{
return;
}
//int mid = Partition(arr,0,end);
int mid = Partition2(arr,0,end);
_QuickSort(arr,0,mid);
_QuickSort(arr,mid + 1,end);
}
//快排(递归的方法)
void QuickSort(int arr[],int size)
{
if(size <= 1)
{
return;
}
_QuickSort(arr,0,size);
}
方法二:填坑法
与交换法没差很多,从前往后找到大于基准值的元素就将该元素填入基准值的位置,那么该元素的位置就相当于一个坑了,然后从后往前找一个小于基准值的元素,将该元素填入上一个坑,此时该位置也是一个坑…………..
图解填坑法:
代码实现:
//挖坑法
int Partition2(int arr[],int left,int right)
{
int start = left;
int end = right - 1;
int key = arr[end];
while(start < end)
{
//找到左边大于基准值的元素
while(start < end && arr[start] <= key)
{
++start;
}
//将大于基准值的元素填入基准值的位置
if(arr[start] > key && start < end)
{
arr[end--] = arr[start];
}
//找到右边小于基准值的元素
while(start < end && arr[end] >= key)
{
--end;
}
//将找到的小于基准值的元素填入合适的位置.
if(arr[end] < key && start < end)
{
arr[start++] = arr[end];
}
}
arr[end] = key;
return start;
}
void _QuickSort(int arr[],int start,int end)
{
if(end - start < 1)
{
return;
}
//int mid = Partition(arr,0,end);
int mid = Partition2(arr,0,end);
_QuickSort(arr,0,mid);
_QuickSort(arr,mid + 1,end);
}
//快排
void QuickSort(int arr[],int size)
{
if(size <= 1)
{
return;
}
_QuickSort(arr,0,size);
}
时间复杂度
最坏的情况:当数组本身就是一个有序的数组时,时间复杂度就是O(N^2);其余的情况下时间复杂度都是O(N*logN).
空间复杂度为:O(1)
快排是一种不稳定的排序算法.