#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int nums[N], help[N];
int n;
//快速排序 - l,j 有序 j+1, r 中 j左边的数都小于等于nums[j]右边的都大于等于nums[j]
void quickSort(int l, int r){
if(l >= r) return;
int x = nums[l+r>>1], i = l-1, j = r+1;
while(i < j){
do i++; while(x > nums[i]);
do j--; while(x < nums[j]);
if(i < j)
swap(nums[i], nums[j]);
}
quickSort(l, j), quickSort(j+1, r);
}
//选择排序 - 每轮都选择剩余元素中 最小的 和 第一个 进行交换
void selectSort() {
for(int i = 0; i < n-1; ++i) {
int cur_min = i;
for(int j = i+1; j < n; ++j) {
if(nums[j] < nums[cur_min]) {
cur_min = j;
}
}
swap(nums[i], nums[cur_min]);
}
}
//插入排序 - 待序元素插入有序元素 因此需要在搜索位置的同时 后移有序元素
void insertSort() {
//从i开始是默认i == 0已经是有序
for(int i = 1; i < n; ++i) {
auto value = nums[i];//必须备份 因为会覆盖
int j = i-1;
while(j >= 0 && nums[j] > value) {
nums[j+1] = nums[j];
--j;
}
nums[j+1] = value;
}
}
//冒泡排序 - 实际上是每轮就确定一个最大的元素(如果按照从小到大排列)
void bubbleSort() {
for(int i = 0; i < n-1; ++i) {
bool flag = false;//这样写在最佳情况下的时间复杂度才会是O(n)
for(int j = 0; j < n-i-1; ++j) {//优化
if(nums[j] > nums[j+1]) {
swap(nums[j], nums[j+1]);
flag = true;
}
}
if(!flag) break;
}
}
//归并排序 - 分治思想,左右数组都是排好序的 然后再合并、统一排序
void mergeSort(int l, int r) {
if(l >= r) return ;
int mid = l+r>>1;
int i = l, j = mid+1, cnts = 0;
mergeSort(l, mid), mergeSort(mid+1, r);
while(i <= mid && j <= r) {
help[cnts++] = nums[i] <= nums[j] ? nums[i++] : nums[j++];
}
while(i <= mid) help[cnts++] = nums[i++];
while(j <= r) help[cnts++] = nums[j++];
for(int i = 0; i < cnts; ++i) {
nums[l++] = help[i];
}
}
//计数排序 - 适合数据比较集中的排序,将元素转换成键值
void countSort() {
auto max_value = *max_element(nums, nums+n);
auto min_value = *min_element(nums, nums+n);
vector<int> count(max_value - min_value + 1);
for(int i = 0; i < n; ++i) {
++count[nums[i]-min_value];
}
/*这样写就结束的话 无法保证数据的稳定性 因为覆盖原数组
int indx = 0;
for(int i = 0; i < count.size(); ++i) {
for(int j = 0; j < count[i]; ++j) {
nums[indx++] = i + min_value;
}
}
*/
//因此 -> 从后面 反向填充数组:相等的先填充后面的,然后减少计数值
for(int i = 1; i < count.size(); ++i) {
count[i] = count[i-1] + count[i];
}
int res[n];
for(int i = n-1; i >= 0; --i) {
auto cnts = count[nums[i]-min_value];
res[cnts-1] = nums[i];
--count[nums[i]-min_value];
}
memcpy(nums, res, sizeof res);
}
//基数排序 - 适合给位数较多的数字进行排序 (几进制的数字就只需要准备几个桶)
void radixSort() {
auto max_value = *max_element(nums, nums+n);
int bit = 0, tmp = max_value;
while(tmp) {
tmp /= 10;
++bit;
}
int radix = 1;
vector<int> count(10);
int res[n];
for(int i = 1; i <= bit; ++i) {
memset(res, 0, sizeof res);
for(int j = 0; j < n; ++j) {
++count[nums[j]/radix%10];
}
for(int j = 1; j < 10; ++j) {
count[j] = count[j-1] + count[j];
}
int indx = 0;
for(int j = n-1; j >= 0; --j) {
int cnts = count[nums[j]/radix%10];
res[cnts-1] = nums[j];
--count[nums[j]/radix%10];
}
memcpy(nums, res, sizeof res);
radix *= 10;
}
}
//桶排序 - 每个桶内部排序后再统一排序
void bucketSort() {
int k = 10;
auto max_value = *max_element(nums, nums+n);
auto min_value = *min_element(nums, nums+n);
int bucket_num = (max_value - min_value) / k + 1;
vector<int> bucket[bucket_num];
for(int i = 0; i < n; ++i) bucket[(nums[i]-min_value)/k].emplace_back(nums[i]);
for(int i = 0; i < bucket_num; ++i) sort(bucket[i].begin(), bucket[i].end());
int indx = 0;
for(int i = 0, j = 0; i < bucket_num; ) {
if(j < bucket[i].size()) nums[indx++] = bucket[i][j++];
else i++, j = 0;
}
}
//堆排序 - 和别的不一样 小标从1开始方便维护,每次都维护堆,将维护完成的放到数组末尾
void down(int u, int sz) {
int tmp = u;
while(2*u <= sz && nums[2*u] < nums[tmp]) tmp = 2*u;
while(2*u+1 <= sz && nums[2*u+1] < nums[tmp]) tmp = 2*u+1;
if(tmp != u) {
swap(nums[tmp], nums[u]);
down(tmp, sz);
}
}
void up(int u) {
while(u/2 && nums[u/2] > nums[u]) {
swap(nums[u/2], nums[u]);
u /= 2;
}
}
void heapSort() {
//建堆
for(int i = n/2; i; --i) down(i, n);
for(int i = n; i > 1; --i) {
swap(nums[1], nums[i]);
down(1, i-1);
}
}
//希尔排序 - 在插入排序一步步移动的基础上优化步长
void shellSort() {
for(int gap = n/2; gap; gap /= 2) {
for(int i = gap; i < n; ++i) {
int tmp = nums[i], j = i;
for( ; j >= gap && tmp < nums[j-gap]; j -= gap) {
nums[j] = nums[j-gap];
}
nums[j] = tmp;
}
}
}
int main(){
cin >> n;
for(int i = 0; i < n; ++i) cin >> nums[i];
//quickSort(0, n-1);
//selectSort();
//insertSort();
//bubbleSort();
//mergeSort(0, n-1);
//countSort();
//radixSort();
bucketSort();
//heapSort();
//shellSort();
for(int i = 0; i < n; ++i) cout << nums[i] << " ";
return 0;
}
十大排序 C++代码
于 2022-09-14 12:41:29 首次发布