• 常见排序算法


    一、冒泡排序(稳定)

    模板:(交换排序)

    1. for (int i = 0; i < ans.size()-1; i++) {//一共排序 n-1 轮,因为最后一个元素不需要比较
    2. for (int j = 0; j < ans.size() - i -1; j++) {
    3. //比较完i轮就是有i个数被排序,所以还剩n-i个数,-1变成下标(即不包含的右边界)
    4. if (ans[j] > ans[j + 1]) {//升序
    5. int temp = ans[j];
    6. ans[j] = ans[j + 1];
    7. ans[j + 1] = temp;
    8. }
    9. }
    10. }

    时间复杂度:O(n^2)

    特点:

    • 简单易实现:不需要额外的数据结构
    • 稳定性:相等元素的相对位置在排序前后不会改变,冒泡排序是稳定的排序算法
    • 效率较低:复杂度较高,适用于小规模的数据排序或者在其他排序算法中作为优化手段的一部分

    适应场景:

    • 由于冒泡排序的效率较低,在处理大量数据时不是首选。
    • 更适用于处理小规模的数据或者在其他排序算法中作为优化手段的一部分。

    二、选择排序

    三、插入排序

    四、希尔排序

    五、归并排序

    六、快速排序(不稳定)

    模板:(交换排序)

    视频链接:秒懂算法快速排序-动画4分钟精讲_哔哩哔哩_bilibili

    1. void quickSort(vector<int>& nums,int left,int right) {
    2. if (left >= right) return;//终止条件
    3. int midnum = nums[left];//选中基准值
    4. int i = left, j = right;
    5. while (i < j) {
    6. while (imidnum) j--;//从右边界找到比基准值小的数
    7. if (i < j) {//比基准值小的数字插入左边槽中 移动左边界
    8. nums[i] = nums[j];
    9. i++;
    10. }
    11. while (i < j && nums[i] < midnum) i++;//从左边界找到比基准值大的数
    12. if (i < j) {//比基准值大的数子插入右边槽中 移动右边界
    13. nums[j] = nums[i];
    14. j--;
    15. }
    16. }
    17. nums[i] = midnum;//将基准值放入左边槽中
    18. quickSort(nums, left, i - 1);//将基准值左边的区间进行快排
    19. quickSort(nums, i + 1, right);
    20. }

    时间复杂度:

    • 平均时间复杂度为  O(nlogn)
    • 最差情况下的时间复杂度为  O(n^2)

    特点:

    • 高效性:平均情况下时间复杂度为 O(nlogn) ,相比于其他排序算法,效率更高
    • 原地排序:不需要额外的辅助空间
    • 分治思想:将排序序列分成大于基准值和小于基准值的两部分,然后分别递归划分和排序
    • 不稳定性:排序过程中相同元素的相对顺序可能会发生变化

    适应场景:

    • 数组排序:排序大规模数字数据
    • 查找第 k 大/小的元素:通过每次划分比较基准值所在的位置与 k 的大小关系,可以只对需要的部分继续进行排序,从而提供查找效率。(只需要判断基准值插入的槽,和 k 相同时,就是查找元素)

    七、堆排序(不稳定)

    排序算法:堆排序【图解+代码】_哔哩哔哩_bilibili

    1. void heapify(vector<int>& arr, int size, int i)
    2. {
    3. int largest = i;
    4. int lson = 2 * i + 1;
    5. int rson = 2 * i + 2;
    6. if (lson < size && arr[largest] < arr[lson])
    7. largest = lson;
    8. if (rson < size && arr[largest] < arr[rson])
    9. largest = rson;
    10. if (largest != i)//当父节点不是最大值
    11. {
    12. swap(arr[i], arr[largest]);//把最大值和父节点值交换
    13. heapify(arr, size, largest);//维护下一层
    14. }
    15. }
    16. void heap_sort(vector<int>& arr)
    17. {
    18. int size = arr.size();
    19. // 建堆
    20. for (int i = size / 2 - 1; i >= 0; i--)
    21. heapify(arr, size, i);
    22. // 排序
    23. for (int i = size - 1; i > 0; i--)
    24. {
    25. swap(arr[0], arr[i]);
    26. heapify(arr, i, 0);
    27. }
    28. }

    时间复杂度O(nlogn)

    特点:

    • 构建初始堆需要 O(n) 的时间,而对每个元素进行堆调整和交换的操作都需要 O(logn) 的时间,共需要进行 n-1 次。
    • 原地排序,不需要额外的存储空间。因此空间复杂度为  O(1) 。
    • 相等元素的相对顺序可能会发生改变,排序不稳定。

    适用场景:

    • 数据量较大且没有进一步的空间限制时非常有效,由于时间复杂度为 O(nlogn) ,因此处理大规模数据时表现良好。
    • 适用于对内存占用有限的场景。
    • 适用于部分排序场景。

    八、计数排序

    九、桶排序

    十、基数排序

  • 相关阅读:
    Speedoffice(excel)文档中min函数如何使用
    TiUP Cluster
    Django(10)ORM聚合查询
    码农的转型之路-这款轮子可以造吗?
    小程序web-view无法打开该页面的解决方法
    什么是IA智能自动化?与RPA+AI有何区别?
    Chrome自动升级了,找不到最新版本的webdriver怎么办?
    Java面向对象(高级)-- static关键字的使用
    C++学习第二十六天----内联函数与引用变量
    大型医院容灾备份平台建设与应用实践
  • 原文地址:https://blog.csdn.net/Ricardo_XIAOHAO/article/details/133101384