C++_排序算法:冒泡排序、插入排序、归并排序、快速排序、堆排序、基数排序、桶排序、计数排序

C++_排序算法—冒泡、插入、归并、快速、堆、基数、桶、计数

所有代码均可直接运行

需要c++11的支持

冒泡排序:

1、思想:

反复交换相邻的元素以达到排序目的,原址排序,平均和最坏时间复杂度都为Θ(n²)。

2、源代码:

#include <iostream>
#include <vector>
#include <random>

using namespace std;

void Bubble_Sort(vector<long long> &v1) {
	for (auto i = 1; i != v1.size(); ++i) {
		for (auto j = v1.size() - 1; j != i - 1; --j) {
			if (v1[j] < v1[j - 1]) {
				swap(v1[j], v1[j - 1]);
			}
		}
	}
}

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

int main() {
	vector<long long> v1 = Random();
	Bubble_Sort(v1);

	for (auto & i : v1)
		cout << i << " ";

	return 0;
}

插入排序:

1、思想:

从后向前逐个比较,类似于扑克牌的排序 ,原址排序,平均和最坏时间复杂度都为Θ(n²)。

它和冒泡排序的区别是,冒泡是一边比较一边交换元素的位置,而插入则是比较完了再交换元素的位置。也就是说,一个元素交换一次位置下来,冒泡只移动了一个位置,而插入则移动了若干位置。

2、源代码:

#include <random>
#include <iostream>
#include <vector>

using namespace std;

void Insertion_Sort(vector<long long> &v1) {
	long long k;
	long long temp_key;
	for (auto j = 1; j != v1.size(); ++j) {
		temp_key = v1[j];
		k = j - 1;
		while (k >= 0 && v1[k] > temp_key) {
			v1[k + 1] = v1[k];
			--k;
		}
		v1[k + 1] = temp_key;
	}
}

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

int main() {
	vector<long long> v1 = Random();
	Insertion_Sort(v1);

	for (auto &temp : v1) {
		cout << temp << " ";
	}

	return 0;
}

归并排序(二路):

1、思想:

一分为n,不断递归,排序,再合并,非原址排序,平均和最坏时间复杂度都为Θ(nlgn)。//lg以2为底

2、源代码:

#include <iostream>
#include <vector>
#include <random>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

void Merge(vector<long long> &v1, vector<long long> &temp_v, size_t p, size_t q, size_t r) {
	size_t leftEnd = q - 1;
	size_t tempPos = p;
	size_t length = r - p + 1;

	while (p <= leftEnd && q <= r) {
		if (v1[p] <= v1[q])
			temp_v[tempPos++] = v1[p++];
		else
			temp_v[tempPos++] = v1[q++];
	}

	while (p <= leftEnd) {
		temp_v[tempPos++] = v1[p++];
	}

	while (q <= r) {
		temp_v[tempPos++] = v1[q++];
	}

	for (auto i = 0; i != length; ++i, --r) {
		v1[r] = temp_v[r];
	}
}

void Merge_Sort(vector<long long> &v1, vector<long long> &temp_v, size_t p, size_t r) {
	if (p < r) {
		auto q = (p + r) / 2;
		Merge_Sort(v1, temp_v, p, q);
		Merge_Sort(v1, temp_v, (q + 1), r);
		Merge(v1, temp_v, p, (q + 1), r);
	}
}

void Merge_Sort(vector<long long> &v1) {
	vector<long long> temp_v(v1.size());
	Merge_Sort(v1, temp_v, 0, (v1.size() - 1));
}

int main() {
	vector<long long> v1 = Random();
	Merge_Sort(v1);

	for (auto &temp : v1)
		cout << temp << " ";

	return 0;
}

快速排序:

1、思想:

给一个阈值,小于阈值的放前面,大于阈值的放后边,不断递归这个过程。
原址排序,其时间复杂度多半取决于阈值的选取。最坏时间复杂度是Θ(n²),平均时间复杂度是Θ(nlgn)。//lg以2为底

1、常规化版本:

源代码:

#include <iostream>
#include <random>
#include <vector>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

size_t Partition(vector<long long> &v1, size_t p, size_t r) {
	auto i = p - 1;
	for (auto j = p; j != r; ++j) {
		if (v1[j] <= v1[r]) {
			++i;
			swap(v1[i], v1[j]);
		}
	}
	swap(v1[i + 1], v1[r]);

	return i + 1;
}

void Quick_Sort(vector<long long> &v1, long long p, long long r) {
	if (p < r) {
		auto q = Partition(v1, p, r);
		Quick_Sort(v1, p, q - 1);
		Quick_Sort(v1, q + 1, r);
	}
}

void Quick_Sort(vector<long long> &v1) {
	size_t b = 0, e = v1.size() - 1;
	Quick_Sort(v1, b, e);
}

int  main() {
	vector<long long> v1 = Random();
	Quick_Sort(v1);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

2、随机化版本:

随机化版本和普通版本的唯一区别就是,随机化选取阈值。

源代码:

#include <iostream>
#include <random>
#include <vector>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

size_t Random_Partition(vector<long long> &v1, size_t p, size_t r) {

	auto ri = p + rand() % (r - p + 1);
	swap(v1[ri], v1[r]);

	auto i = p - 1;
	for (auto j = p; j != r; j++) {
		if (v1[j] <= v1[r]) {
			++i;
			swap(v1[i], v1[j]);
		}
	}
	swap(v1[i + 1], v1[r]);

	return i + 1;
}

void Quick_Sort_Random(vector<long long> &v1, long long  p, long long  r) {
	if (p < r) {
		auto q = Random_Partition(v1, p, r);
		Quick_Sort_Random(v1, p, q - 1);
		Quick_Sort_Random(v1, q + 1, r);
	}
}

void Quick_Sort_Random(vector<long long> &v1) {
	size_t b = 0, e = v1.size() - 1;
	Quick_Sort_Random(v1, b, e);
}

int   main() {
	vector<long long> v1 = Random();
	Quick_Sort_Random(v1);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

堆排序(最大堆):

1、思想:

堆排序是建立在堆这个数据结构上的。堆又是建立在二叉树上的。最大堆有这样的性质:根节点总比叶结点大,同样,最小堆就是叶结点总比根节点大。
原址排序。最坏时间复杂度为O(nlgn)。//lg以2为底

2、源代码:

#include <iostream>
#include <random>
#include <vector>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(-100000000, 100000000);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

void Max_Heapify(vector<long long> &v1, size_t i, size_t length) {
	size_t l = 2 * i + 1;
	size_t r = 2 * i + 2;
	size_t largest = i;

	if (l < length && v1[l] > v1[i]) {
		largest = l;
	}
	if (r < length && v1[r] > v1[largest]) {
		largest = r;
	}
	if (largest != i) {
		swap(v1[i], v1[largest]);
		Max_Heapify(v1, largest, length);
	}
}

void Build_Max_Heap(vector<long long> &v1) {
	for (auto i = v1.size() / 2 - 1; i != -1; --i) {
		Max_Heapify(v1, i, v1.size() - 1);
	}
}

void Heap_Sort(vector<long long> &v1) {
	Build_Max_Heap(v1);
	for (auto i = v1.size() - 1; i != 0; --i) {
		swap(v1[0], v1[i]);
		Max_Heapify(v1, 0, i);
	}
}

int main() {
	vector<long long> v1 = Random();
	Heap_Sort(v1);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

基数排序:

1、思想:

其是一种卡片机上的排序算法,给定n个有d位的整数,其中每一位数都有k个可能的取值,从低位到高位,依次排序。
例如有n组日期(年、月、日),先排日期,再月,最后是年。
原址排序。最坏和平均时间复杂度都为Θ(d (n + k))。

2、源代码:

//Tan Chuanqi's thought.   chuanqi.tan@gmail.com

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(0, 99999);
	vector<long long>                          v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

auto max_dim = 5;

void Radix_Sort(vector<long long> &v1, long long dim) { 
	stable_sort(v1.begin(), v1.end(), [&dim](long long temp_1, long long temp_2) {
		auto Dim_Num = [](long long &temp_num, long long &d) -> long long {
			for (auto i = 1; i <= max_dim - d; ++i) {
				temp_num /= 10;
			}
			return temp_num % 10;
		};
		return Dim_Num(temp_1, dim) < Dim_Num(temp_2, dim);
	});

	if (dim != 1) {
		Radix_Sort(v1, dim - 1);
	}
}

int main() {
	vector<long long> v1 = Random();
	Radix_Sort(v1, max_dim);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

桶排序:

1、思想:

桶排序将[0,1)区间划分为n个大小相同的子区间,或称为桶。然后将n个数分别放入各个桶中。再对各个桶中的数据分别排序。最后再将各个桶中的数据合并。
非原址排序。最坏时间复杂度为Θ(n²),平均时间复杂度为Θ(n)。

2、源代码:

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>

using namespace std;

vector<double> Random() {
	static default_random_engine             e;
	static uniform_real_distribution<double> u(0, 1);
	vector<double>                           v1;

	for (auto i = 0; i != 10000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

void Bucket_Sort(vector<double> &v1) {
	vector<vector<double>> bucket(10);

	for (auto &i : v1) {
		bucket[10 * i].push_back(i);
	}

	for (auto &i : bucket) {
		stable_sort(i.begin(), i.end());
	}

	v1.clear();

	for (auto &i : bucket) {
		v1.insert(v1.end(), i.begin(), i.end());
	}
}

int main() {
	vector<double> v1 = Random();
	Bucket_Sort(v1);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

计数排序:

1、思想:

假设n个输入元素中的每一个都是在0到k区间的整数,对于元素x,计算出小于x的元素个数s,那么排序后x的位置为s+1(以0为首位置的数组,元素位置依然为s)。
它和之前所讲的排序最大不同就是,它不是比较,而是计算,但是,它有致命弱点,所排序值必须小于数组下标的最大值,并且只能排自然数。
非原址排序。最坏和平均时间复杂度都为Θ(k + n)。

2、源代码:

#include <iostream>
#include <vector>
#include <random>

using namespace std;

vector<long long> Random() {
	static default_random_engine               e;
	static uniform_int_distribution<long long> u(0, 99999);
	vector<long long>                          v1;

	for (auto i = 0; i != 100000; ++i) {
		v1.push_back(u(e));
	}

	return v1;
}

void Counting_sort(vector<long long> &v1) {
	vector<long long> temp_v1 = v1;
	vector<long long> temp_count(v1.size(), 0);

	for (auto &j : v1) {
		++temp_count[j];
	}

	for (auto i = 1; i != temp_count.size(); ++i) {
		temp_count[i] += temp_count[i - 1];
	}

	for (auto j = v1.size() - 1; j != -1; --j) {
		temp_v1[temp_count[v1[j]] - 1] = v1[j];
		--temp_count[v1[j]];
	}

	v1 = temp_v1;
}

int main() {
	vector<long long> v1 = Random();
	Counting_sort(v1);

	for (auto &i : v1) {
		cout << i << " ";
	}

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值