十大排序 C++代码

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值