• 分治之归并,快速排序


    所谓归并排序,就是把一段需要排序的序列分成2部分,分别完成排序之后,然后进行合并,从而完成对整个序列的排序。众所周知,归并排序用了分治的思想,即把原任务分成和原任务相同,但规模更小的几个子问题。分别解决,从而达到解决原问题的效果。

    ex:给定以下数组a[10]={ 6 ,5 ,7 ,1 ,4 ,3 ,2 ,5 ,9 ,8},要求按从大到小的顺序排序,归并的思路如下:

    1.将其分成两部分6 5 7 1 4 和 3 2 5 9 8

    2.(以前半部分为例,下同)显然需要继续分,前半部分分成 6 5 7 和1 4,

    3.再次分成 6 5 和 7

    4.将 6  5分成 6 和5

    5.接下来就是归并了,归并函数Merge()里有两个"指针",记录两部分的头,然后分别进行比较,将小的(或大的)先放在b[]数组里,比如对以上过程,先放5,再放6,放好之后拷贝进原数组,再与上次分好的进行比较,放7,以此类推(即新的组里的每一个元素都需要比较,而不是简单的与排好的部分首元素或者尾元素比较),如何让它回到上层呢,由此很自然想到递归解决。

    代码如下:

    #include <iostream>
    
    using namespace std;
    
    
    void Sort(int a[],int m,int n,int b[]);
    void Merge(int a[],int m,int k,int n,int b[]);
    
    int *a;
    int *b;
    
    
    int main()
    {
        int n;
        cin>>n;
        a=new int [n];
        b=new int [n];
        for(int i=0;i<n;i++)
            cin>>a[i];
        Sort(a,0,n-1,b);
        for(int i=0;i<n;i++)
            cout<<a[i]<<" ";
        return 0;
    }
    void Sort(int *a,int m,int n,int b[])
    {
        if(m<n)
        {
            int k=m+(n-m)/2;
            Sort(a,m,k,b);
            Sort(a,k+1,n,b);
            Merge(a,m,k,n,b);
        }
    }
    void Merge(int a[],int m,int k,int n,int b[])
    {
        int pb=0;
        int p1=m,p2=k+1;
        while(p1<=k&&p2<=n)
        {
            if(a[p1]<a[p2])
                b[pb++]=a[p1++];
            else
                b[pb++]=a[p2++];
        }
        while(p1<=k)
            b[pb++]=a[p1++];
        while(p2<=n)
            b[pb++]=a[p2++];
        for(int i=0;i<n-m+1;++i)
            a[m+i]=b[i];
    }

    好了,既然已经掌握了归并排序,接下来我们再来看一个排序——快速排序。

    同样是分治的思想,同样是刚才的数组,具体怎么实现排序呢。

    1.我们选择一个标记数字,方便起见,选择a[0],令k=a[0]

    2.将比a[0]小的数移动到a[0]的左边,比a[0]大的数移动到a[0]的右边,例如,对于6 ,5 ,7 ,1 ,4 ,3 ,2 ,5 ,9 ,8,a[0]=6,设置一个i,j分别从第一个和最后一个位置开始(即i=0,j=9),首先从j开始,此时i=0,如果a[j]>=k,--j,否则交换a[j],a[i],得到5,5,7,1,4,3,2,6,9,8,接下来j停止,从i开始,如果a[i]<k,++i,否则交换a[i],a[j],得到5,5,2,1,4,3,7,6,9,8,继续从j开始,发现已经没有比k还大的数了,程序会一直--j,直到i=j,此时我们跳出循环

    3.数组已经被分成6左边的和右边的两部分,此时我们继续按步骤2对左右两部分进行处理,一直处理到只剩下一个数(递归终止条件),就可以得到我们想要的结果了。

    代码如下:

    #include <iostream>
    
    using namespace std;
    
    
    int b[10]={1,0,7,5,6,9,8,4,3,2};
    void swap(int &a,int &b);
    void quicksort(int a[],int s,int e);
    int main()
    {
        quicksort(b,0,9);
        for(int i=0;i<10;i++)
            cout<<b[i]<<" ";
        return 0;
    }
    void swap(int &a,int &b)
    {
        int temp=a;
        a=b;
        b=temp;
    }
    void quicksort(int a[],int s,int e)
    {
        if(s>=e)
            return;
        int k=a[s];
        int i=s,j=e;
        while(i!=j)
        {
            while(j>i&&a[j]>=k)
                --j;
                swap(a[i],a[j]);
            while(i<j&&a[i]<=k)
                ++i;
            swap(a[i],a[j]);
        }
        quicksort(a,s,i-1);
        quicksort(a,i+1,e);
    }

    以上就是分治之归并排序,快速排序了,如有什么疏漏的地方和不足之处,欢迎批评指正。。。

  • 相关阅读:
    SQL Server 添加数据库没有权限等
    网站图片优化的重要性与技巧方案
    5年前端经验小伙伴教你纯css3实现饼状图
    css3 斜切角/斜边的实现方式来自BAT大神的出品
    Validate表单验证插件之常用参数介绍
    html实现邮箱发送邮件_js发送邮件至指定邮箱功能
    css重设样式_清除浏览器的默认样式
    大厂前端工程师教你如何使用css3绘制任意角度扇形+动画
    WordPress教程之如何批量删除未引用(无用)的TAG标签
    css引入的方式有哪些_四种css的引入方式与特点
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450777.html
Copyright © 2020-2023  润新知