C++ 快速排序实现

28 篇文章 5 订阅

快速排序

#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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值