快速排序
一、快速排序
-
基本思路:
快速排序使用分治的思想,通过Partition的动作将原数据集以一个枢轴pivot分割为小于pivot和大于pivot的两个部分,递归地在这两个部分继续分割,直到当前数据集大小为1,这时也完成了排序。 -
算法
PARTITION (array, left, right):
pivot = array[left]
temp=left
while (left<right):
while (left<right && array[right]>pivot):
right=right-1
while (left<right && array[left]<=pivot):
left=left+1
swap (left, right)
swap (left, temp)
解释:分别从右、左两边遍历当前数据集,交换数据实现以pivot为中心的分割
该算法在实现过程中有一些细节要注意:
(1)pivot应该存储实际数据而不是下标,因为下标left在后面会修改
(2)从小到大排序应该从右开始遍历:如果从左开始,那么循环中最后一次交换完执行left=left+1,然后left==right,也就是说这时的array[left]>pivot,执行最后一个交换,一个大于pivot的数会被交换到pivot前面
(3)array[left]<=pivot:至少要有这个等号
QUICKSORT (array, left, right):
if left<right
pivot = PARTITION (array, left, right)
QUICKSORT (array, left, pivot-1)
QUICKSORT (array, pivot+1, right)
-
复杂度:O(nlogn)
-
运行截图
-
源代码
解释:程序用了三种Partition的方法,前两个只有微小的不同,第三个来自于算法导论,不同在于它是单向遍历,而非前两个分别从首尾遍历。
int Partition1(vector<int> &list, int left, int right)
{
int pivot = list[left];
int templeft = left;
while(left<right)
{
while(left<right && list[right]>=pivot)
{
right--;
}
swap(list,left,right);
while(left<right && list[left]<=pivot)
{
left++;
}
swap(list,right,left);
}
}
int Partition2(vector<int> &list, int left, int right)
{
int pivot = list[left];
int templeft = left;
while(left<right)
{
while(left<right && list[right]>pivot)
{
right--;
}
while(left<right && list[left]<=pivot)
{
left++;
}
swap(list,left,right);
}
swap(list,left,templeft);
return left;
}
int Partition3(vector<int> &list, int left, int right)
{
int pivot = list[right];
int i=left-1;
for(int j=left;j<right;j++)
{
if(list[j]<=pivot)
{
i++;
swap(list,i,j);
}
}
swap(list,i+1,right);
return i+1;
}
void QuickSort(vector<int> &list, int left, int right)
{
if(left<right)
{
int partition = Partition(list,left,right);
QuickSort(list,left,partition-1);
QuickSort(list,partition+1,right);
}
}
void swap(vector<int> &list, int a, int b)
{
int temp = list[a];
list[a] = list[b];
list[b] = temp;
}
二、基于快速排序的第k小数
-
基本思路:
递归调用Partition函数,直到枢轴的下标为k。 -
运行截图
-
源代码
解释:实际程序与快速排序非常相似,只是递归条件变化。
int Partition(int list[], int left, int right)
{
int pivot = left;
while(left<right)
{
while(list[right]>list[pivot] && left<right) right--;
while(list[left]<=list[pivot] && left<right) left++;
swap(list,left,right);
}
swap(list,left,pivot);
return left;
}
int QuickSortGetTopK(int list[], int left, int right, int k)
{
int partition = -1;
if(left<right && k)
{
partition = Partition(list,left,right);
if(partition == k)
return k;
else if(partition < k)
return QuickSortGetTopK(list,partition+1,right,k);
else
return QuickSortGetTopK(list,left,partition-1,k);
}
}
void swap(int list[], int a, int b)
{
int temp = list[a];
list[a] = list[b];
list[b] = temp;
}