• 浅谈排序算法(冒泡,插入,归并)


    对于数据的排序,有多种方法,对应这不同的时间复杂度(效率不同)。

    ​一、冒泡排序(Bubble Sort)

            冒泡排序(Bubble Sort)是一种简单的排序算法。

             算法思路:

                   1. 从第一对相邻数据开始到最后一组相邻数据比较,两两依次比较,最后一组数据结束时,数组 下标n对应的数即为最大数

                    2.重复上述操作,直至下标为n-1 (下标为n的数已经是最大的,不需要重复操作)

                    3.最后重复操作直至不需要再比较任意一对数(即总共进行n次)

            时间复杂度 O(x^{2})

            图示(省略比较不交换的操作):

     冒泡排序代码:

    1. #include<cstdio>
    2. #include<iostream>
    3. using namespace std;
    4. int a[1001];
    5. int n;
    6. int main()
    7. {
    8. scanf("%d",&n);
    9. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    10. for(int i=1;i<=n;i++)
    11. for(int j=1;j<=n-i;j++)
    12. {
    13. if(a[j]>a[j+1]) swap(a[j],a[j+1]);
    14. }
    15. for(int i=1;i<=n;i++) printf("%d ",a[i]);
    16. return 0;
    17. }

     二、插入排序(Insert sort)

           插入排序很好理解,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

            算法思路:

                    1.默认第一个元素为已排序序列

                    ​2.取出下一个元素,在已排序序列中从后向前扫描

    ​                3.如果该元素(已排序)大于新元素,将该元素移到下一位置(前移一位)

    ​                4.重复操作3,直到找到已排序的元素小于或者等于新元素的位置,并将新元素插入到该位置后

                    5.重复2~4操作,直至对最后一个元素插入操作结束。

                时间复杂度:O(x^{2})

     关键操作:步骤3 从后向前扫描 以上图④为例

    代码实现插入排序: 

    1. #include<cstdio>
    2. #include<iostream>
    3. using namespace std;
    4. int a[1001];
    5. int n;
    6. int main()
    7. {
    8. scanf("%d",&n);
    9. for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    10. for(int i=1;i<n;i++)
    11. {
    12. for(int j=i+1;j>=1;j--)
    13. if(a[j]<a[j-1]) swap(a[j],a[j-1]);
    14. }
    15. for(int i=1;i<=n;i++) printf("%d ",a[i]);
    16. return 0;
    17. }

    三、归并排序(Merge sort)

            归并排序(Merge sort)是一种采用分治法的排序方法,将已有的子序列合并,合并成一个有

    序的新序列。时间复杂度:O(nlogn)

            算法思路(分支法):

            1.分:将原序列分成相应的子序列(二分方法)。时间复杂度为 O(logn ),相比上述两种排序方法的效率大大提高,因此更适合数据范围更大的情况。            

            

    1. // “分”的伪代码
    2. void merge(int l,int r)
    3. {
    4. int mid=l+(r-l)/2; // 二分
    5. if(l<r)
    6. {
    7. merge(l,mid);
    8. merge(mid+1,r);
    9. merge_sort(l,mid,r); //
    10. }
    11. }

             2.并:将分的子序列合并成一个新的有序数列(合并的过程是线性的,时间复杂度为O(n)

            

            “并”的过程思路很简单,但与递归结合代码实现较难

               将 [ l , r ] [ mid+1 , r ] 的序列合并,采用线性方法,如图所示:

    从两个序列的第一个数一次比较,取出较小的数放入新的有序数组,然后再将新数组赋值到原来的数组中。

    1. void merge_sort(int l,int mid,int r) // 将[l,mid]与[mid+1,r]的序列合并
    2. {
    3. int i=l,j=mid+1,k=l;
    4. while(i!=mid+1 && j!=r+1) // 采用线性的方法
    5. {
    6. if(a[i]>a[j])
    7. {
    8. b[k++]=a[j];
    9. j++;
    10. }
    11. else
    12. {
    13. b[k++]=a[i];
    14. i++;
    15. }
    16. }
    17. while(i!=mid+1) b[k++]=a[i++]; // 将剩下未被完全取出的序列依次取出放入新数组
    18. while(j!=r+1) b[k++]=a[j++];
    19. for(int i=l;i<=r;i++) a[i]=b[i];
    20. }

     一个关于归并排序的思考:

                    归并过程通过将两个序列合并成一个有序数列,需要通过比较两个序列首端的元素大小,并依次取出,这个过程是线性的,需要保证这两个序列也是有序的,但这两个序列会不会有序呢?为什么有序呢?

            通过每次递归加上不断重复更新原数组,保证每次并的过程结果都会是有序的,所以当合并两个序列是,这两个序列也是有序的。

            

  • 相关阅读:
    企业级AI大模型如何落地?
    初识vue.route
    超详细Docker部署SpringBoot+Vue项目(三更博客项目部署)
    SSM巢湖学院校园报修系统毕业设计-附源码021813
    机器学习笔记之最优化理论与方法(六)无约束优化问题——最优性条件
    轻断食原理:胰岛素水平
    SpreadJS 16.2.6 Crack
    《向量数据库指南》——Milvus Cloud向量数据库的优势
    【分享】微信公众号在 “集简云平台“ 集成应用的常见问题与解决方案
    rsync远程同步
  • 原文地址:https://blog.csdn.net/Zhang_Qin123/article/details/136325794