排序算法总结
排序算法 | 平均时间复杂度 | 最好时间复杂度 | 最坏时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | n^2 | n | n^2 | 1 | 稳定 |
选择排序 | n^2 | n^2 | n^2 | 1 | 不稳定 |
插入排序 | n^2 | n | n^2 | 1 | 稳定 |
希尔排序 | n^1.3 | n^2 | n | 1 | 不稳定 |
归并排序 | nlogn | nlogn | nlogn | n | 稳定 |
快速排序 | nlogn | nlogn | n^2 | logn 递归 1 非递归 | 不稳定 |
堆排序 | nlogn | nlogn | nlogn | 1 | 不稳定 |
桶排序 | m*nlogn ,m桶数 | n+k | 根据内部 | ||
计数排序 | n+k | n+k | n+k | n+k | 稳定 |
基数排序 | d*(n+k) d是位数,k是进制 | d*(n+k) | d*(n+k) | n+k | 稳定 |
算法分析
算法代码
冒泡排序
/**
* @brief 冒泡排序
*
* @param v
*/
void mao_pao_sort(vector<int> &v)
{
for (int i = 0; i < v.size() - 1; ++i)
{
for(int j = 0; j < v.size() - 1 - i; ++j)
{
if (v[j] > v[j + 1])
::swap(v[j], v[j + 1]);
}
}
}
选择排序
/**
* @brief 选择排序
*
* @param v
*/
void select_sort(vector<int> &v)
{
int len = v.size();
for(int i = 0; i < len - 1; ++i)
{
int min_i = i;
for (int j = i; j < len; ++j)
{
if (v[j] < v[min_i])
min_i = j;
}
::swap(v[i], v[min_i]);
}
}
插入排序
/**
* @brief 插入排序
*
* @param v
*/
void insert_sort(vector<int> &v)
{
for(int i = 1; i < v.size(); ++i)
{
int cur = v[i], j = i - 1;
while(j >= 0 && v[j] >= cur)
{
v[j + 1] = v[j];
--j;
}
v[j + 1] = cur;
}
}
希尔排序
/**
* @brief 方式二希尔排序辅助函数
*
* @param v
* @param start
* @param gap
*/
void min_xier_sort(vector<int> &v,const int &start, const int &gap)
{
for(int i = start + gap; i < v.size(); ++i)
{
int j = i - gap;
int cur = v[i];
while(j >= start && v[j] > cur)
{
v[j + gap] = v[j];
j -= gap;
}
v[j + gap] = cur;
}
}
/**
* @brief 希尔排序
*
* @param v
*/
void xier_sort(vector<int> &v)
{
// 方式一
for(int gap = v.size() / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < v.size(); ++i)
{
for(int j = i - gap;j >= 0 && v[j] > v[j + gap]; j-=gap)
::swap(v[j + gap], v[j]);
}
}
// 方式二
// for(int gap = v.size() / 2; gap > 0; gap /= 2)
// {
// for (int i = 0; i < gap; ++i)
// {
// min_xier_sort(v, i, gap);
// }
// }
}
归并排序
/**
* @brief 归并排序辅助函数
*
* @param v
* @param start
* @param end
* @param res
*/
void merge(vector<int> &v, int start, int end, int *res)
{
int mid = (end + start) / 2, p1 = start, p2 = mid + 1, p_res = start;
while(p1 <= mid && p2 <= end)
{
if (v[p1] <= v[p2])
res[p_res++] = v[p1++];
else
res[p_res++] = v[p2++];
}
while(p1 <= mid) res[p_res++] = v[p1++];
while(p2 <= end) res[p_res++] = v[p2++];
while(start <= end)
{
v[start] = res[start];
++start;
}
}
/**
* @brief 真正的归并排序
*
* @param v
* @param start
* @param end
* @param res
*/
void __gui_sor(vector<int> &v, int start, int end, int *res)
{
if (end - start == 0)
return;
__gui_sor(v, start, (end + start) / 2, res);
__gui_sor(v, (end + start) / 2 + 1, end, res);
merge(v, start, end, res);
}
/**
* @brief 归并排序
*
* @param v
*/
void gui_sort(vector<int> &v)
{
int *res = new int[v.size()];
__gui_sor(v, 0, v.size() - 1, res);
delete [] res;
}
快速排序
/**
* @brief 快速排序辅助函数
*
* @param v
* @param l
* @param r
* @return int
*/
int partition(vector<int> &v, int l, int r)
{
int p = l + 1;
for(int i = p; i <= r; ++i)
{
if (v[i] < v[l])
{
::swap(v[i], v[p]);
++p;
}
}
::swap(v[p - 1], v[l]);
return p - 1;
}
/**
* @brief 真正的快排
*
* @param v
* @param l
* @param r
*/
void __quick_sort(vector<int> &v, int l, int r)
{
if (l >= r)
return;
int p = partition(v, l, r);
__quick_sort(v, l, p - 1);
__quick_sort(v, p + 1, r);
}
/**
* @brief 快速排序
*
* @param v
*/
void quick_sort(vector<int> &v)
{
__quick_sort(v, 0, v.size() - 1);
}
堆排序
/**
* @brief 调整堆,实际上是下沉操作
*
* @param v
* @param n
* @param size
*/
void adjust_heap(vector<int> &v, const int &n, const int &size)
{
int l = 2*n + 1,
r = 2*n + 2,
max_n = n;
if (l < size && v[l] > v[max_n])
max_n = l;
if (r < size && v[r] > v[max_n])
max_n = r;
if (max_n != n)
{
::swap(v[n], v[max_n]);
adjust_heap(v, max_n, size);
}
}
/**
* @brief 建堆,自下而上
*
* @param v
* @param size
*/
void build_heap(vector<int> &v, const int &size)
{
int l = size / 2;
for(int i = l; i >=0; --i)
{
adjust_heap(v, i, size);
}
}
/**
* @brief 堆排序
*
* @param v
*/
void heap_sort(vector<int> &v)
{
build_heap(v, v.size());
for (int i = v.size() - 1; i > 0; --i)
{
::swap(v[0], v[i]);
adjust_heap(v, 0, i);
}
}
计数排序
/**
* @brief 计数排序
*
* @param v
*/
void count_sort(vector<int> &v, int min_num = -100, int max_num = 100)
{
const int range = max_num - min_num + 1;
int *arr = new int[range]();
for(const auto &num: v)
++arr[num - min_num];
int p = 0;
for (int i = 0; i < range; ++i)
{
while(arr[i] != 0)
{
v[p++] = i + min_num;
--arr[i];
}
}
delete [] arr;
}
桶排序
/**
* @brief 桶排序
*
* @param v
* @param buck_num 桶的数量,默认为5个桶
*/
void bucket_sort(vector<int> &v, int step = 3)
{
// 求出最大最小值
int min_num = INT_MAX , max_num = INT_MIN;
for(const auto &t: v)
{
if (t < min_num)
min_num = t;
if (t > max_num)
max_num = t;
}
vector<vector<int>> buckets((max_num - min_num) / step + 1);
for(const auto &t: v) // 将数据映射到每个桶中
buckets[(t - min_num) / step].push_back(t);
int res_pos = 0;
for(auto &bucket: buckets)
{
for(int i = 1; i < bucket.size(); ++i)
{
int j = i - 1;
while(j >= 0 && bucket[j] > bucket[j + 1])
{
::swap(bucket[j], bucket[j + 1]);
--j;
}
}
for (const auto &t: bucket)
v[res_pos++] = t;
}
}
基数排序
/**
* @brief 基数排序, 只适用于自然数
*
*/
void base_sort(vector<int> &v)
{
int max = *max_element(v.begin(), v.end());
int max_dit = 1;
while((max /= 10) != 0)
++max_dit;
vector<vector<int>> base_v(10);
for (int i = 0, dev = 1, mod = 10; i < max_dit; ++i,mod*=10,dev *=10)
{
for(const auto &x: v)
base_v[(x % mod) / dev].push_back(x);
int v_pos = 0;
for(auto & min_base_v: base_v)
{
for(const auto &x : min_base_v)
v[v_pos++] = x;
min_base_v.clear();
}
}
}
算法测试
#include<iostream>
#include<queue>
#include<functional>
#include<memory>
#include<unordered_map>
#include<string>
#include<algorithm>
#include<math.h>
#include<unordered_set>
#include<queue>
#include<functional>
#include<random>
#include<sys/utime.h>
#include<time.h>
using namespace std;
template <typename T>
void swap(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
/**
* @brief 冒泡排序
*
* @param v
*/
void mao_pao_sort(vector<int> &v)
{
for (int i = 0; i < v.size() - 1; ++i)
{
for(int j = 0; j < v.size() - 1 - i; ++j)
{
if (v[j] > v[j + 1])
::swap(v[j], v[j + 1]);
}
}
}
/**
* @brief 选择排序
*
* @param v
*/
void select_sort(vector<int> &v)
{
int len = v.size();
for(int i = 0; i < len - 1; ++i)
{
int min_i = i;
for (int j = i; j < len; ++j)
{
if (v[j] < v[min_i])
min_i = j;
}
::swap(v[i], v[min_i]);
}
}
/**
* @brief 插入排序
*
* @param v
*/
void insert_sort(vector<int> &v)
{
for(int i = 1; i < v.size(); ++i)
{
int cur = v[i], j = i - 1;
while(j >= 0 && v[j] >= cur)
{
v[j + 1] = v[j];
--j;
}
v[j + 1] = cur;
}
}
/**
* @brief 方式二希尔排序辅助函数
*
* @param v
* @param start
* @param gap
*/
void min_xier_sort(vector<int> &v,const int &start, const int &gap)
{
for(int i = start + gap; i < v.size(); ++i)
{
int j = i - gap;
int cur = v[i];
while(j >= start && v[j] > cur)
{
v[j + gap] = v[j];
j -= gap;
}
v[j + gap] = cur;
}
}
/**
* @brief 希尔排序
*
* @param v
*/
void xier_sort(vector<int> &v)
{
// 方式一
for(int gap = v.size() / 2; gap > 0; gap /= 2)
{
for (int i = gap; i < v.size(); ++i)
{
for(int j = i - gap;j >= 0 && v[j] > v[j + gap]; j-=gap)
::swap(v[j + gap], v[j]);
}
}
// 方式二
// for(int gap = v.size() / 2; gap > 0; gap /= 2)
// {
// for (int i = 0; i < gap; ++i)
// {
// min_xier_sort(v, i, gap);
// }
// }
}
/**
* @brief 归并排序辅助函数
*
* @param v
* @param start
* @param end
* @param res
*/
void merge(vector<int> &v, int start, int end, int *res)
{
int mid = (end + start) / 2, p1 = start, p2 = mid + 1, p_res = start;
while(p1 <= mid && p2 <= end)
{
if (v[p1] <= v[p2])
res[p_res++] = v[p1++];
else
res[p_res++] = v[p2++];
}
while(p1 <= mid) res[p_res++] = v[p1++];
while(p2 <= end) res[p_res++] = v[p2++];
while(start <= end)
{
v[start] = res[start];
++start;
}
}
/**
* @brief 真正的归并排序
*
* @param v
* @param start
* @param end
* @param res
*/
void __gui_sor(vector<int> &v, int start, int end, int *res)
{
if (end - start == 0)
return;
__gui_sor(v, start, (end + start) / 2, res);
__gui_sor(v, (end + start) / 2 + 1, end, res);
merge(v, start, end, res);
}
/**
* @brief 归并排序
*
* @param v
*/
void gui_sort(vector<int> &v)
{
int *res = new int[v.size()];
__gui_sor(v, 0, v.size() - 1, res);
delete [] res;
}
/**
* @brief 快速排序辅助函数
*
* @param v
* @param l
* @param r
* @return int
*/
int partition(vector<int> &v, int l, int r)
{
int p = l + 1;
for(int i = p; i <= r; ++i)
{
if (v[i] < v[l])
{
::swap(v[i], v[p]);
++p;
}
}
::swap(v[p - 1], v[l]);
return p - 1;
}
/**
* @brief 真正的快排
*
* @param v
* @param l
* @param r
*/
void __quick_sort(vector<int> &v, int l, int r)
{
if (l >= r)
return;
int p = partition(v, l, r);
__quick_sort(v, l, p - 1);
__quick_sort(v, p + 1, r);
}
/**
* @brief 快速排序
*
* @param v
*/
void quick_sort(vector<int> &v)
{
__quick_sort(v, 0, v.size() - 1);
}
/**
* @brief 调整堆,实际上是下沉操作
*
* @param v
* @param n
* @param size
*/
void adjust_heap(vector<int> &v, const int &n, const int &size)
{
int l = 2*n + 1,
r = 2*n + 2,
max_n = n;
if (l < size && v[l] > v[max_n])
max_n = l;
if (r < size && v[r] > v[max_n])
max_n = r;
if (max_n != n)
{
::swap(v[n], v[max_n]);
adjust_heap(v, max_n, size);
}
}
/**
* @brief 建堆,自下而上
*
* @param v
* @param size
*/
void build_heap(vector<int> &v, const int &size)
{
int l = size / 2;
for(int i = l; i >=0; --i)
{
adjust_heap(v, i, size);
}
}
/**
* @brief 堆排序
*
* @param v
*/
void heap_sort(vector<int> &v)
{
build_heap(v, v.size());
for (int i = v.size() - 1; i > 0; --i)
{
::swap(v[0], v[i]);
adjust_heap(v, 0, i);
}
}
/**
* @brief 计数排序
*
* @param v
*/
void count_sort(vector<int> &v, int min_num = -100, int max_num = 100)
{
const int range = max_num - min_num + 1;
int *arr = new int[range]();
for(const auto &num: v)
++arr[num - min_num];
int p = 0;
for (int i = 0; i < range; ++i)
{
while(arr[i] != 0)
{
v[p++] = i + min_num;
--arr[i];
}
}
delete [] arr;
}
/**
* @brief 桶排序
*
* @param v
* @param buck_num 桶的数量,默认为5个桶
*/
void bucket_sort(vector<int> &v, int step = 3)
{
// 求出最大最小值
int min_num = INT_MAX , max_num = INT_MIN;
for(const auto &t: v)
{
if (t < min_num)
min_num = t;
if (t > max_num)
max_num = t;
}
vector<vector<int>> buckets((max_num - min_num) / step + 1);
for(const auto &t: v) // 将数据映射到每个桶中
buckets[(t - min_num) / step].push_back(t);
int res_pos = 0;
for(auto &bucket: buckets)
{
for(int i = 1; i < bucket.size(); ++i)
{
int j = i - 1;
while(j >= 0 && bucket[j] > bucket[j + 1])
{
::swap(bucket[j], bucket[j + 1]);
--j;
}
}
for (const auto &t: bucket)
v[res_pos++] = t;
}
}
/**
* @brief 基数排序, 只适用于自然数
*
*/
void base_sort(vector<int> &v)
{
int max = *max_element(v.begin(), v.end());
int max_dit = 1;
while((max /= 10) != 0)
++max_dit;
vector<vector<int>> base_v(10);
for (int i = 0, dev = 1, mod = 10; i < max_dit; ++i,mod*=10,dev *=10)
{
for(const auto &x: v)
base_v[(x % mod) / dev].push_back(x);
int v_pos = 0;
for(auto & min_base_v: base_v)
{
for(const auto &x : min_base_v)
v[v_pos++] = x;
min_base_v.clear();
}
}
}
/**
* @brief Create a randon object
*
* @param num
* @param min
* @param max
* @return vector<int>
*/
vector<int> create_randon(long num, int min, int max)
{
vector<int> res(num);
uniform_int_distribution<int> r(min,max);
default_random_engine e(time(0));
for(auto &x: res)
x = r(e);
return res;
}
bool check(const vector<int> v)
{
for(int i = 0; i < v.size() - 1; ++i)
{
if (v[i] > v[i + 1])
return false;
}
return true;
}
int main()
{
int min = 0, max = pow(10,3), nums = pow(10, 4);
setbuf(stdout, NULL);
clock_t s_time, e_time;
s_time = clock();
vector<int> my_list = create_randon(nums, min, max);
vector<int> m_list;
e_time = clock();
cout<<"create time"<<(e_time - s_time) * 1.0 / CLOCKS_PER_SEC<<"s\n";
vector<pair<string, function<void(vector<int>&)>>> functions = {
{"冒泡", mao_pao_sort},
{"选择", select_sort},
{"插入", insert_sort},
{"希尔", xier_sort},
{"归并", gui_sort},
{"快排", quick_sort},
{"堆排序", heap_sort},
{"计数排序", bind(count_sort, std::placeholders::_1, min, max)},
{"桶排序", bind(bucket_sort, std::placeholders::_1, 3)},
{"基数排序", base_sort}
};
for(auto &cp: functions)
{
m_list.assign(my_list.begin(), my_list.end());
s_time = clock();
cp.second(m_list);
e_time = clock();
printf("%-14s: times %fs,check %s\n", cp.first.c_str(), (e_time - s_time) * 1.0 / CLOCKS_PER_SEC, check(m_list)?"true":"false");
}
m_list.assign(my_list.begin(), my_list.end());
s_time = clock();
sort(m_list.begin(), m_list.end());
e_time = clock();
printf("%-14s: times %fs,check %s\n", "库排序算法", (e_time - s_time) * 1.0 / CLOCKS_PER_SEC, check(m_list)?"true":"false");
}