常用的排序算法模板

快速排序

思想:基于二分思想,划分一个主元。把整个数组通过主元划分成两部分,小于主元的在左边,大于的在右边。对左右部分递归划分即可完成排序

时间复杂度:

时间复杂度在最佳情况是 O ( n l o g n ) O(nlog_n) O(nlogn),但是如果分界点元素选择不当可能会退化到 O ( n 2 ) O(n^2) O(n2),但是这种情况比较少见(比如数组完全逆序),如果随机选择分界点的话,时间复杂度能够稳定在 O ( n l o g n ) O(nlog_n) O(nlogn)。另外如果元素中相同元素数量比较多的话,也会降低排序性能。

空间复杂度在 O ( l o g n ) O(log_n) O(logn)水平,属于堆栈调用,在最坏的情况下空间复杂度还是 O ( n ) O(n) O(n),平均情况下复杂度是 O ( l o g n ) O(log_n) O(logn)

快速排序是不稳定的,因为包含跳跃式交换元素位置。

void quick_sort(int nums[], int left, int right) {
    if (left >= right) return ;
    int low = left + 1, high = right;
    while (low <= high) {
        if (nums[low] < nums[left]) low++;
        else swap(nums[low], nums[high--]); // 交换两个元素值
    }
    swap(nums[left], nums[--low]);
    quick_sort(nums, left, low - 1);
    quick_sort(nums, low + 1, right);
}

冒泡排序

思想:像泡泡一样,左右互相比较,把最大的往右移动

void bubble_sort(int nums[], int length) {
    for (int i = length - 1; i >= 1; i--) { // 最大有序区间
        for (int j = 0; j < i; j++) {
            if (nums[j] > nums[j + 1]) {
                swap(nums[j], nums[j + 1]);
            }
        }
    }
}

选择排序

思想:从无序区里选择一个最大的数或者最小的数**交换(因此这个基于数组的算法不稳定)**到有序区间的一端,在无序区选某个数

// 选择排序        选择n个元素的最大值和最后一个元素交换
void select_sort(int nums[], int length) {
    for (int i = length - 1; i >= 1; i--) {
        int max_index = 0;
        for (int j = 0; j <= i; j++) {
            if (nums[j] > nums[max_index]) {
                max_index = j;
            }
        }
        if (nums[max_index] > nums[i]) {
            swap(nums[max_index], nums[i]);
        }
    }
}

插入排序

思想:从无序区间的第一个数插入到有序区间里,在有序区间里面做排序

优化:二分插入

// 插入排序       最小的维护在左区间
void insert_sort(int nums[], int length) {
    for (int i = 1; i < length; i++) {
        int j = i;
        while (j > 0 && nums[j] < nums[j - 1]) {
            swap(nums[j], nums[j - 1]);
            j--;
        }
    }
}

归并排序

void merge_sort(int nums[], int left, int right) {
    if (left >= right) return ;
    int mid = (left + right) / 2; // 从中间进行划分
    merge_sort(nums, left, mid);
    merge_sort(nums, mid + 1, right);
    int temp[right - left + 1]; // 临时数组
    int i = left, j = mid + 1;
    int index = 0;
    while (i <= mid && j <= right) {
        if (nums[i] <= nums[j]) temp[index++] = nums[i++];
        else temp[index++] = nums[j++];
    }
    while (i <= mid) temp[index++] = nums[i++];
    while (j <= right) temp[index++] = nums[j++];
    // 拷贝回原来的数组
    for (int i = 0; i < index; i++) {
        nums[left + i] = temp[i];
    }
}

总结

排序算法最好情况平均情况最差情况空间复杂度稳定性
冒泡排序 n 2 n^2 n2 n 2 n^2 n2 n 2 n^2 n21
选择排序 n 2 n^2 n2 n 2 n^2 n2 n 2 n^2 n21
插入排序 n n n n 2 n^2 n2 n 2 n^2 n21
希尔排序 n l o g n nlog_n nlogn n 4 / 3 n^{4/3} n4/3 n 4 / 3 n^{4/3} n4/31
二叉树排序 n l o g n nlog_n nlogn n l o g n nlog_n nlogn n 2 n^2 n2n
归并排序 n l o g n nlogn nlogn n l o g n nlogn nlogn n l o g n nlogn nlognn
快速排序 n l o g n nlog_n nlogn n l o g n nlogn nlogn n 2 n^2 n2 l o g n logn logn
堆排序 n l o g n nlog_n nlogn n l o g n nlogn nlogn n l o g n nlogn nlogn1
计数排序n+rn+rn+r
桶排序n+rn+rn+r
基数排序nk/dnk/d n + 2 d n+2^d n+2d
TimSortn n l o g n nlog_n nlogn n l o g n nlog_n nlognn
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值