首先, 让我们了解一下,Let go
桶排序
目录
桶排序的过程
1. 设置一个定量的数组作为空桶
2.遍历序列, 并将元素一一对应到相应的桶中
3.对每一个不是空的桶进行排序
4.从不是空的桶的讲元素放回原来的序列
稳定性
如果使用较稳定的内定排序,同时,也不会改变相应的顺序,我们就可以桶排序是一个稳定的排序算法。
时间复杂度
它的平均时间复杂度处于是为 O(n) 最坏的情况处于O(n^2) 将值域平均分成 n块 + 排序 + 重新合并元素
适合场景
如果元素不多,那么桶排序就成为了YYDS,数据分布均匀的情况。
我们直接上代码
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, w, a[N];
vector<int> bucket[N];
void insertion_sort(vector<int>& A) {
for (int i = 1; i < A.size(); ++i) {
int key = A[i];
int j = i - 1;
while (j >= 0 && A[j] > key) {
A[j + 1] = A[j];
--j;
}
A[j + 1] = key;
}
}
void bucket_sort() {
int bucket_size = w / n + 1;
for (int i = 0; i < n; ++i) {
bucket[i].clear();
}
for (int i = 1; i <= n; ++i) {
bucket[a[i] / bucket_size].push_back(a[i]);
}
int p = 0;
for (int i = 0; i < n; ++i) {
insertion_sort(bucket[i]);
for (int j = 0; j < bucket[i].size(); ++j) {
a[++p] = bucket[i][j];
}
}
}
#include <iostream>
#include <algorithm>
using namespace std;
void bucketSort(int arr[], int n, int k) {
int max_val = *max_element(arr, arr+n); // 找到数组中的最大值
int bucket[k]; // 创建桶数组
for (int i = 0; i < k; i++) {
bucket[i] = 0; // 将桶数组初始化为0
}
for (int i = 0; i < n; i++) {
int index = (arr[i] * k) / max_val; // 根据最大值和当前值计算出应该放在哪个桶中
bucket[index]++; // 在对应的桶中计数
}
for (int i = 0, j = 0; i < k; i++) {
while (bucket[i] > 0) { // 将桶中的数据按顺序放回原数组中
arr[j++] = i; // 将当前桶中的数据赋值给原数组
bucket[i]--; // 将桶中的计数减1
}
}
}
int main() {
int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; // 待排序的数组
int n = sizeof(arr) / sizeof(arr[0]); // 数组长度
int k = 5; // 桶的大小
bucketSort(arr, n, k); // 桶排序
for (int i = 0; i < n; i++) {
cout << arr[i] << " "; // 输出排好序的数组
}
return 0;
}
基数排序
基数排序的流程
1.先找出原始数组arr最大值,求出最大值有多少个位数digitLen
2.对原始数组每个位(个位、十位、百位、千位、...)分别进行计数排序,即digitLen次最外层循环
3.每个位计数排序完成后,将结果复制到原始数组arr中,并且清除原始计数countArr数组后,再进行下一个位的计数排序,直到完成所有位的排序,则完成整个数组排序
稳定性
它按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。基数排序法是属于稳定性的排序。在某些时候,基数排序法的效率高于其它的稳定性排序法。
时间复杂度
时间复杂度为O(nlog(r)m),其中r为所采取的基数,而m为堆数。
适合场景
基数排序的适用场景包括:
- 大数据排序:随着大数据时代的到来,处理海量数据面临挑战。在这种情况下,传统的排序算法可能无法满足需求。基数排序通过将数据按照不同的位数进行排序,可以有效地处理大规模数据集。其时间复杂度为O(kn),其中k是数字的位数,n是数据集的大小。因此,基数排序在大数据排序场景中具有明显的优势。
- 字符串排序:除了对数字进行排序,基数排序也可以用于字符串排序。在某些应用中,例如字典排序、电话号码排序等,我们需要对字符串进行排序。基数排序可以按照字符串的每个字符进行排序,从而实现字符串的排序功能。这种应用场景在信息检索、数据分析等领域非常常见。
Code
#include <algorithm>
#include <stack>
#include <tuple>
#include <vector>
using std::copy; // from <algorithm>
using std::make_tuple;
using std::stack;
using std::tie;
using std::tuple;
using std::vector;
typedef unsigned int u32;
typedef unsigned int* u32ptr;
void MSD_radix_sort(u32ptr first, u32ptr last) {
const size_t maxW = 0x100000000llu;
const u32 maxlogW = 32; // = log_2 W
const u32 W = 256; // 计数排序的值域
const u32 logW = 8;
const u32 mask = W - 1; // 用位运算替代取模,详见下面的 key 函数
u32ptr tmp =
(u32ptr)calloc(last - first, sizeof(u32)); // 计数排序用的输出空间
typedef tuple<u32ptr, u32ptr, u32> node;
stack<node, vector<node>> s;
s.push(make_tuple(first, last, maxlogW - logW));
while (!s.empty()) {
u32ptr begin, end;
size_t shift, length;
tie(begin, end, shift) = s.top();
length = end - begin;
s.pop();
if (begin + 1 >= end) continue; // elements <= 1
// 计数排序
u32 cnt[W] = {};
auto key = [](const u32 x, const u32 shift) { return (x >> shift) & mask; };
for (u32ptr it = begin; it != end; ++it) ++cnt[key(*it, shift)];
for (u32 value = 1; value < W; ++value) cnt[value] += cnt[value - 1];
// 求完前缀和后,计算相同关键字的元素范围
if (shift >= logW) {
s.push(make_tuple(begin, begin + cnt[0], shift - logW));
for (u32 value = 1; value < W; ++value)
s.push(make_tuple(begin + cnt[value - 1], begin + cnt[value],
shift - logW));
}
u32ptr it = end;
do {
--it;
--cnt[key(*it, shift)];
tmp[cnt[key(*it, shift)]] = *it;
} while (it != begin);
copy(tmp, tmp + length, begin);
}
}
希尔排序
希尔排序的流程
- 将待排序序列分为若干子序列(每个子序列的元素在原始数组中间距相同);
- 对这些子序列进行插入排序;
- 减小每个子序列中元素之间的间距,重复上述过程直至间距减少为 。
稳定性
希尔排序是一种不稳定的排序算法。
时间复杂度
希尔排序的最优时间复杂度为O(n) 。
使用场景
- 当数据规模较大,但数据量不均匀,且分布不平时,希尔排序的效果会比插入排序更好。
- 当数据量非常大,且需要快速排序时,希尔排序可以作为一种选择。
Code
template <typename T>
void shell_sort(T array[], int length) {
int h = 1;
while (h < length / 3) {
h = 3 * h + 1;
}
while (h >= 1) {
for (int i = h; i < length; i++) {
for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
std::swap(array[j], array[j - h]);
}
}
h = h / 3;
}
}
总结
排序算法(英语:Sorting algorithm)是一种将一组特定的数据按某种顺序进行排列的算法。排序算法多种多样,性质也大多不同。进制无论多少,都可以,不仅只有10进制,100 1000 10000都可以,合理利用排序,一起享受ac的快乐。