美文网首页
四种基本排序方法(C/C++实现)

四种基本排序方法(C/C++实现)

作者: 点一下我的id | 来源:发表于2018-12-19 09:30 被阅读0次

    设要将序列(Q, H, C, Y, P, A, M, S, R, D, F, X)中的关键码按字母序的升序重新排列,则:
    冒泡排序一趟扫描的结果是 H C Q P A M S R D F X Y ;
    二路归并排序一趟扫描的结果是 H Q C Y A P M S D R F X;
    快速排序一趟扫描的结果是 F H C D P A M Q R S Y X;
    堆排序初始建堆的结果是 Y S X R P C M H Q D F A 。(大根堆)
    快速排序的基本思想:
    1任取一个元素 (如第一个) 为中心。
    2所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表。
    3对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个。
    注:
    ①每一趟的子表的形成是采用从两头向中间交替式逼近法;
    ②由于每趟中对各子表的操作都相似,可采用递归算法。
    快速排序一趟扫描解析:取子序第一个数据项Q作为中心,指针low指向Q(Q被取出来,已经为空,待存放high指针值比Q小的数),指针high指向最后Y。
    初始值 Q, H, C, Y, P, A, M, S, R, D, F, X
    注:%代表low,&代表high

    %, H, C, Y, P, A, M, S, R, D, F, X& //取出Q ,low指向%,high指向X&。
    %, H, C, Y, P, A, M, S, R, D, F&, X //X比Q大,high往左移一位,指向F。
    F, H%, C, Y, P, A, M, S, R, D, &, X //F比Q小,存入#的位置,
    F, H, C%, Y, P, A, M, S, R, D, &, X
    F, H, C, Y%, P, A, M, S, R, D, &, X
    F, H, C, %, P, A, M, S, R, D&, Y, X
    F, H, C, D, P%, A, M, S, R, &, Y, X
    F, H, C, D, P, A%, M, S, R, &, Y, X
    F, H, C, D, P, A, M%, S, R, &, Y, X
    F, H, C, D, P, A, M, S%, R, &, Y, X
    F, H, C, D, P, A, M, %, R&, S, Y, X
    F, H, C, D, P, A, M, %&, R, S, Y, X
    F, H, C, D, P, A, M, Q, R, S, Y, X
    二趟扫描:Q分两个子序(F, H, C, D, P, A, M)和(R, S, Y, X ),这两个子序分别按照上面的思路排序,便是快排。

    四种排序方法

    注:为研究排序本身,我们的数组a[0]设为哨兵,数据从a[1]开始。
    排序算法分类
    规则不同
    1.插入排序
    2.交换排序(冒泡排序、快速排序)
    3.选择排序
    4.归并排序(二路归并排序、排序过程、两个有序子序列的归并、归并排序(递归)、C++实现、算法分析)

    直接插入排序

    冒泡排序

    一趟冒泡排序:设要排序的数组是A[1]……A[N],首先比较数组的第一个数和第二个数关系,逆序移动,正序不变,重复到第N-1个数,这个过程称为一趟快速排序。
    原理:两两交换,大数据就慢慢往一个方向移动,就像水里的泡泡一样,该排序很简单,无需多言。
    暴力代码

    #include<iostream>
    using namespace std;
    #define MAXSIZE 100
    #define OK 1
    typedef int Status;
    typedef struct
    {
        int *a;
        int length;
    }SqList;
    Status BubbleSort(SqList &L)
    {
        int n=L.length,*a=L.a;
        for(int i=1;i<=n-1;i++)     //趟数n-1
        {
            for(int j=1;j<=n-i;j++)  //比较次数n-i
            {
                if(a[j]>a[j+1])     //如果前面的数比后面的大,交换
                {
                    int temp=a[j];     //定义t为整数型,用于暂时保存大的值
                    a[j]=a[j+1];    //交换次序,a[j+1]较小,放前面
                    a[j+1]=temp;       //a[j+1]从暂时保存的大的值t取回来
                }
            }
        }
        return OK;
    }
    Status InitList(SqList &L)
    {
        L.a=new int(MAXSIZE);
        L.length=0;
        return OK;
    }
    Status Print(SqList L)
    {
        for(int i=1;i<=L.length;i++)
            cout<<L.a[i]<<" ";
        return OK;
    }
    int main()
    {
        int n=6,a[7]={0,21,25,49,25,16,8};//定义 n为整数,a为整数组
        SqList l;
        InitList(l);
        l.a=a;
        l.length=n;
        BubbleSort(l);
        Print(l);
        return 0;
    }
    

    每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素;一旦下趟没有交换,还可提前结束排序
    优化代码

    #include<iostream>
    using namespace std;
    #define MAXSIZE 100
    #define OK 1
    typedef int Status;
    typedef struct
    {
        int *a;
        int length;
    }SqList;
    Status BubbleSort(SqList &L)
    {
        int n=L.length,*a=L.a;
        for(int i=1;i<=n-1;i++)     //趟数n-1
        {
            int flag=1;
            for(int j=1;j<=n-i;j++)  //比较次数n-i
            {
                if(a[j]>a[j+1])     //如果前面的数比后面的大,交换
                {
                    int temp=a[j];     //定义t为整数型,用于暂时保存大的值
                    a[j]=a[j+1];    //交换次序,a[j+1]较小,放前面
                    a[j+1]=temp;       //a[j+1]从暂时保存的大的值t取回来
                    flag=0;
                }
            }
            if(flag==1)//一趟结束没有交换,提前结束排序
                break;
        }
        return OK;
    }
    Status InitList(SqList &L)
    {
        L.a=new int(MAXSIZE);
        L.length=0;
        return OK;
    }
    Status Print(SqList L)
    {
        for(int i=1;i<=L.length;i++)
            cout<<L.a[i]<<" ";
        return OK;
    }
    int main()
    {
        int n=6,a[7]={0,21,25,49,25,16,8};//定义 n为整数,a为整数组
        SqList l;
        InitList(l);
        l.a=a;
        l.length=n;
        BubbleSort(l);
        Print(l);
        return 0;
    }
    

    冒泡排序(优化代码)总结:
    时间复杂度:
    平均情况O(n²)
    最好情况O(n),只需 1趟排序,比较次数为 n-1,不移动
    最坏情况O(n²),需 n-1趟排序,第i趟比较n-i次,移动3(n-i)次


    Screen Shot 2018-12-19 at 10.18.59.png

    空间度杂度:O(1)

    稳定性:稳定

    快速排序

    一趟快速排序:设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

    快速排序(Quicksort)是对冒泡排序(Bubblesort)的一种改进。
    基本思想:
    任取一个元素 (如第一个) 为中心
    所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表;
    对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个

    简单选择排序

    二路归并排序

    一趟2-路归并排序:设要排序的数组是A[1]……A[N],首先划分n/2个子序,每个子序正序不变,逆序移动,这个过程叫一趟2-路归并排序。
    归并:将两个或两个以上的有序表组合成一个新有序表
    2-路归并排序
    排序过程
    初始序列看成n个有序子序列,每个子序列长度为1
    两两合并,得到n/2个长度为2或1的有序子序列
    再两两合并,重复直至得到一个长度为n的有序序列为止

    两个有序子序列的归并

    l设两个有序表存放在同一数组中相邻的位置上:R[low..mid]和R[mid + 1..high]

    l每次分别从两个表中取出一个记录进行关键字的比较,将较小者放入T[1ow..high]中

    l重复此过程,直至其中一个表为空,最后将另一非空表中余下的部分直接复制到T中。

    void Merge(RedType R[],RedType T[],int low,int mid,int high)
    {   
        int i=low;int j=mid+1;int k=low; 
        while(i<=mid&&j<=high)  //将R中记录由小到大地并入T中
        {
            if(R[i].key<=R[j].key) 
                T[k++]=R[i++]; 
            else 
                T[k++]=R[j++];    
        }                   
        while(i<=mid) T[k++]=R[i++];    //将剩余的R[low..mid]复制到T中 
        while(j<=high) T[k++]=R[j++];//将剩余的R[j.high]复制到T中 
    }
    

    归并排序(递归)

    2-路归并排序将R[low..high]中的记录归并排序后放入T[low..high]中。当序列长度等于1时,递归结束,否则:

    u① 将当前序列一分为二,求出分裂点mid= ë(low+high)/2û;

    u②对子序列R[low..mid]递归,结果放入S[low..mid]中;

    u③对子序列R[mid + 1..high]递归,结果放入S[mid + 1..high]中;

    u④调用算法Merge,将S[low..mid]和S[mid + 1..high]归并为T[low..high]。

    void MSort(RedType R[],RedType T[],int low,int high)
    {  
        RedType S[MAXSIZE];
        if(low==high) 
        {
            T[low]=R[low];
        }
        else
        { 
            int mid=(low+high)/2;       //将当前序列一分为二,求出分裂点mid 
            MSort(R,S,low,mid);     //R[low..mid]递归,结果放入S[low..mid] 
            MSort(R,S,mid+1,high);//R[mid+1..high]递归,结果放入S[mid+1..high]
            Merge(S,T,low,mid,high);//将S[low..mid]和S[mid+1..high]归并到T[low..high]
        }                       
    } 
    

    C++实现

    #include<iostream>
    using namespace std;
    #define MAXSIZE 100
    typedef struct
    {
        int key;
    }RedType;
    void Merge(RedType R[],RedType T[],int low,int mid,int high)
    {   
        int i=low;int j=mid+1;int k=low; 
        while(i<=mid&&j<=high)  //将R中记录由小到大地并入T中
        {
            if(R[i].key<=R[j].key) 
                T[k++]=R[i++]; 
            else 
                T[k++]=R[j++];    
        }                   
        while(i<=mid) T[k++]=R[i++];    //将剩余的R[low..mid]复制到T中 
        while(j<=high) T[k++]=R[j++];//将剩余的R[j.high]复制到T中 
    }
    void MSort(RedType R[],RedType T[],int low,int high)
    {  
        RedType S[MAXSIZE];
        if(low==high) 
        {
            T[low]=R[low];
        }
        else
        { 
            int mid=(low+high)/2;       //将当前序列一分为二,求出分裂点mid 
            MSort(R,S,low,mid);     //R[low..mid]递归,结果放入S[low..mid] 
            MSort(R,S,mid+1,high);//R[mid+1..high]递归,结果放入S[mid+1..high]
            Merge(S,T,low,mid,high);//将S[low..mid]和S[mid+1..high]归并到T[low..high]
        }                       
    } 
    int main()
    {
        RedType R[MAXSIZE];
        RedType T[MAXSIZE];
        R[1].key=3;
        R[2].key=2;
        R[3].key=1;
        MSort(R,T,1,3);
        for(int i=1;i<=3;i++) cout<<T[i].key<<" ";
        return 0;
    }
    //3 2 1
    //2 3 1
    //1 2 3
    

    算法分析
    时间效率:O(nlog2n)

    空间效率:O(n)

    稳 定 性:稳定

    相关文章

      网友评论

          本文标题:四种基本排序方法(C/C++实现)

          本文链接:https://www.haomeiwen.com/subject/odsdkqtx.html