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