#include <bits/stdc++.h>
using namespace std;
/*
实现了快速排序
算法基本思想:
1.从数列中挑出一个元素,称为 "基准"(pivot);
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;素
一般情况下复杂度:O(nlogn),最坏情况(基本有序)时间复杂度:O(n^2)
*/
int Partition(int a[], int l, int r){
//以A[l]为基准,进行排序划分,使得左边元素均比A[l小,右边元素均比A[l]大,并且成功找到划分位置
a[0] = a[l]; //引入枢纽元素暂存位置,减少交换次数
while (l < r)
{
while (l < r && a[r] >= a[0]){r -= 1;} //从右往左找到第一个小于基准元素的元素
//元素交换,
a[l] = a[r];
while (l < r && a[l] <= a[0]){l += 1;} //从左往右找到第一个大于基准元素的元素
//元素交换
a[r] = a[l];
}
a[l] = a[0];
return l;
}
void Qucik(int a[], int l, int r){
if(l <= r){
int p = Partition(a, l, r);
//对左右分别进行快排
Qucik(a, l, p-1);
Qucik(a, p+1, r);
}
else
return;
}
int main(){
int a[100];
for(int i = 1; i <= 5; i++)
cin>>a[i];
Qucik(a, 1, 5);
for(int i = 1; i <= 5; i++)
cout<<a[i];
return 0;
}
在求解第k小元素时,同样可以用快排,当找到分割位置正好为k时,就返回退出。参考算法每日一题 - 寻找第K小的数
随机选择一个数作为基准:
#include "bits/stdc++.h"
using namespace std;
int Partition(vector<int>& nums, int low, int high){
//对low--high区间元素进行交换,并返回分界线元素对应的下标
if(low == high)
return low;
int rd = (rand() % (high - low + 1)) + low;
swap(nums[rd], nums[low]);
int temp = nums[low];
int l = low, h = high;
//为什么要先从右侧扫描再到左边:观察这一过程其实是枢纽元素值不断向中间靠近的过程
//同时枢纽元素就是左侧第一个元素,只能和右侧不满足条件的元素交换才是对的
while(l < h){
//从右侧找到第一个小于枢纽元素的值,并交换
while(l < h && nums[h] >= temp){
h--;
}
// nums[l] = nums[h];
swap(nums[l], nums[h]);
//从左侧找到第一个大于枢纽元素的值,并交换
while(l < h && nums[l] <= temp){
l++;
}
// nums[h] = nums[l];
swap(nums[l], nums[h]);
}
// nums[l] = temp;
return l;
}
void QuickSort(vector<int>& nums, int low, int high){
// cout << k << "-----" << endl;
if(low < high){
int middle;
middle = Partition(nums, low, high);
cout << "low: " << low << ", middle: " << middle << ",high : " << high << ", val: " << nums[middle] << endl;
QuickSort(nums, low, middle-1);
QuickSort(nums, middle+1, high);
}
}
int main(){
vector<int> nums = {3,2,1,5,6,4};
int low = 0, high = nums.size() - 1;
QuickSort(nums, low, high);
for(auto a: nums)
cout << a << " ";
cout << endl;
}