快速排序
#include <iostream>
#include <string>
#include<vector>
#include <algorithm>
#include <time.h>
using namespace std;
class Less
{
public:
template<typename T1, typename T2>
bool operator()(const T1& a, const T2& b)
{
return a < b;
}
};
class Greater
{
public:
template<typename T1, typename T2>
bool operator()(const T1& a, const T2& b)
{
return a > b;
}
};
template<typename T, typename compare >
void quickSort(int left, int right, vector<T>& v, compare cmp)
{
if (left >= right)
return;
int idx = rand() % (right - left + 1) + left; //在区间范围中随机找一个作为基准
swap(v[left], v[idx]);
T base = v[left];
int i = left;
int j = right;
while (i < j)
{
if (cmp(base, v[i])) //比基准值小(或者大)的值放到后面去
{
swap(v[i], v[j]);
j--;
}
else
i++;
}
//此时i位置右边肯定全部是比base值小(或者大)的数,再判断一下i位置
i = cmp(base, v[i]) ? i - 1 : i;
v[left] = v[i];
v[i] = base; //基准数放到i位置,此时左边比基准小,右边比基准大
for (int k = 0; k < v.size(); k++)
{
if (k == i)
printf("[%d],", v[k]);
else
printf("%d,", v[k]);
}
cout << endl;
quickSort(left, i - 1, v, cmp); //确定基准位置,分别处理左右两个区间
quickSort(i + 1, right, v, cmp);
}
int main()
{
srand(time(0));
vector<int> v{ 4,6,1,9,4,143,23,56 ,1 };
int n = v.size();
//quickSort(0, n - 1, v);
quickSort(0, n - 1, v, Greater());
for_each(v.begin(), v.end(), [](int& x) {
cout << x << endl; });
return 0;
}
测试结果是:
数组中第k大的数(快排解决)
#include <iostream>
#include <string>
#include<vector>
#include <algorithm>
#include <time.h>
using namespace std;
class Less
{
public:
template<typename T1, typename T2>
bool operator()(const T1& a, const T2& b)
{
return a < b;
}
};
class Greater
{
public:
template<typename T1, typename T2>
bool operator()(const T1& a, const T2& b)
{
return a > b;
}
};
template<typename T, typename compare >
int quickSort(int left, int right, vector<T>& v, compare cmp, int index)
{
if (left > right)
return -1;
int idx = rand() % (right - left + 1) + left; //在区间范围中随机找一个作为基准
swap(v[left], v[idx]);
T base = v[left];
int i = left;
int j = right;
while (i <= j)
{
if (cmp(base, v[i])) //比基准值小(或者大)的值放到后面去
{
swap(v[i], v[j]);
j--;
}
else
i++;
}
//此时i-1位置右边肯定全部是比base值小(或者大)的数
i = i-1;
v[left] = v[i];
v[i] = base; //基准数放到i位置,左边比基准小,右边比基准大
/*for (int k = 0; k < v.size(); k++)
{
if (k == i)
printf("[%d],", v[k]);
else
printf("%d,", v[k]);
}
cout << endl;*/
if (i == index)
return v[i];
else if (i > index)
return quickSort(left, i - 1, v, cmp, index); //确定基准位置,分别处理左右两个区间
else
return quickSort(i + 1, right, v, cmp, index);
}
int main()
{
srand(time(0));
vector<int> v{ 4,6,1,9,4,143,23,56 ,1 };
int n = v.size();
//quickSort(0, n - 1, v);
cout << quickSort(0, n - 1, v, Less(), n - 3); //找第三大的数
/*for_each(v.begin(), v.end(), [](int& x) {
cout << x << endl; });*/
return 0;
}
三路快排
上面的快排思路对重复元素较多的数组效率很差,用三路快排思路解决
参考此处思路
#include <iostream>
#include <string>
#include<vector>
#include <algorithm>
#include <time.h>
#include<chrono>
#include<iomanip>
using namespace std;
template<typename T>
void quickSort3Ways(vector<T>& arr, int left, int right)
{
//if (right - left <= 40) { /* 对递归到数据量较小时使用插入排序 */
// __insertSortMG<T>(arr, left, right);
// return;
//}
if (left >= right)
return;
swap(arr[left], arr[rand() % (right - left + 1) + left]); // 随机化找到一个元素作为"基准"元素
T base = arr[left];
int lt = left; // 将<base的分界线的索引值lt初始化为第一个元素的位置(也就是<base部分的最后一个元素所在位置)
int gt = right + 1; // 将>base的分界线的索引值gt初始化为最后一个元素right的后一个元素所在位置(也就是>base部分的第一个元素所在位置)
int i = left + 1; // 将遍历序列的索引值i初始化为 left+1
while (i < gt) { // 循环继续的条件
if (arr[i] < base) {
std::swap(arr[i], arr[lt + 1]); // 如果当前位置元素<v,则将当前位置元素与=base部分的第一个元素交换位置
i++; // i++ 考虑下一个元素
lt++; // lt++ 表示<base部分多了一个元素
}
else if (arr[i] > base) { // 如果当前位置元素>base,则将当前位置元素与>base部分的第一个元素的前一个元素交换位置
std::swap(arr[i], arr[gt - 1]); // 此时i不用动,因为交换过来的元素还没有考虑他的大小
gt--; // gt-- 表示>v部分多了一个元素
}
else { // 如果当前位置元素=base 则只需要将i++即可,表示=base部分多了一个元素
i++;
}
}
swap(arr[left], arr[lt]); // 上面的遍历完成之后,将整个序列的第一个元素(也就是"基准"元素)放置到合适的位置
// 也就是将它放置在=v部分即可
quickSort3Ways<T>(arr, left, lt - 1); // 对<base部分递归调用quickSort3Ways函数进行三路排序
quickSort3Ways<T>(arr, gt, right); // 对>base部分递归调用quickSort3Ways函数进行三路排序
}
int main()
{
srand(time(0));
vector<int> v;
int cnt = 1000000;
while (cnt--)
{
v.push_back(rand() % 10000 + 1);
}
int n = v.size();
auto begin = chrono::high_resolution_clock::now();
quickSort3Ways(v, 0, n - 1);
auto end = chrono::high_resolution_clock::now();
cout << "quickSort3Ways耗费时间" << endl;
cout << "time: " << chrono::duration_cast<chrono::microseconds>(end - begin).count() * 1e-6 << "s" << endl; //秒计时
/*for_each(v.begin(), v.end(), [](int& x) {
cout << x << endl; });*/
begin = chrono::high_resolution_clock::now();
sort(v.begin(), v.end());
end = chrono::high_resolution_clock::now();
cout << "sort耗费时间" << endl;
cout << "time: " << chrono::duration_cast<chrono::microseconds>(end - begin).count() * 1e-6 << "s" << endl; //秒计时
return 0;
}