zoukankan      html  css  js  c++  java
  • 总容易混淆的排序算法:直接选择、冒泡(鸡尾酒)、直接插入(二分插入)(希尔)

    稳定不稳定看相等元素排序前和排序后的相对顺序是否改变。

    O(n2)

    直接选择(不稳定):选择出最小的放在第一位;选择出次小的放在第二位;......

    代码:

    #include <iostream>
    using namespace std;
    //直接选择排序算法描述:
    /*
    1、第一层遍历:以未排序的第一个元素作为最小值
    2、第二层遍历:对剩下的未排序元素进行遍历,小于最小值则交换值
    3、得到最小的元素组成排序序列,以此类推,第二小的元素也会排入到排序好的序列中。
    4、重复直至排序完全
    */    //==》O(n^2)
    void Swap08(int a[], int i,int j)
    {
        int tmp;
        tmp=a[i];
        a[i]=a[j];
        a[j]=tmp;
    }
    
    void SelectSeq(int a[],int num)
    {
        int min=0;
        for(int i=0;i<num-1;i++)    //最后一个序列是单独的一个元素,不需要再排序
        {
            min=i;//1、选择未排序序列的第一个值为最小的值
            for(int j=i+1;j<num;j++)  //遍历其余未排序的值,如果小于最小值,则交换值
            {
                if(a[i]>a[j])
                    Swap08(a,i,j);
            }
        }
    }
    
    int main08()
    {
        int a[]={12,8,20,5,9,16,7,30};
        int num=sizeof(a)/sizeof(a[0]);
        SelectSeq(a,num);
        for(int i=0;i<num;i++)
        {
            cout<<a[i]<<" ";
        }
        return 0;
    }

    冒泡(稳定):两两比较,最大的放后边;直到最大的放在末尾。

    代码:

    #include <iostream>
    using namespace std;
    //冒泡排序算法描述:
    /*
    1、比较相邻元素,如果前一个比后一个大,则交换位置。
    2、对每一对相邻的元素做同样的工作,从第一对到最后一对,做完一次循环后,最后元素则是最大的。
    3、针对以上元素重复以上步骤,除了最后一个。
    4、重复对越来越少的元素做以上动作,直至没有可交换的对。
    */    //==》O(n^2)
    void Swap09(int a[], int i,int j)
    {
        int tmp;
        tmp=a[i];
        a[i]=a[j];
        a[j]=tmp;
    }
    
    void BubbleSeq(int a[],int len)
    {
        for(int j=0;j<len-1;j++)
        {
            for(int i=0;i<len-1-j;i++)
            {
                if(a[i]>a[i+1])
                    Swap09(a,i,i+1);
            }
        }
        return;
    }
    
    int main09()
    {
        int a[]={12,8,20,5,9,16,7,30};
        int len=sizeof(a)/sizeof(a[0]);
        BubbleSeq(a,len);
        for(int i=0;i<len;i++)
        {
            cout<<a[i]<<" ";
        }
        return 0;
    }

    ==》改进:鸡尾酒排序

    代码:

    #include <iostream>
    using namespace std;
    //鸡尾酒排序算法描述:
    /*
    1、设两个索引,一个索引第一位,一个索引最末尾。
    2、单层循环,一遍最大冒泡,一次最小冒泡。
    3、重复做以上动作,直到排序好。
    */    //==》O(n^2)
    
    void Swap11(int a[], int i,int j)
    {
        int tmp;
        tmp=a[i];
        a[i]=a[j];
        a[j]=tmp;
    }
    void CocktailSeq(int a[],int len)
    {
        int left=0;
        int right=len-1;
        while(left<right)
        {
            for(int i=left;i<right;i++)
            {
                if(a[i]>a[i+1])
                    Swap11(a,i,i+1);
            }
            right--;
            for(int j=right;j>left;j--)
            {
                if(a[j]<a[j-1])
                    Swap11(a,j,j-1);
            }
            left++;
        }
        return; 
    }
    
    int main11()
    {
        int a[]={12,8,20,5,9,16,7,30};
        int len=sizeof(a)/sizeof(a[0]);
        CocktailSeq(a,len);
        for(int i=0;i<len;i++)
        {
            cout<<a[i]<<" ";
        }
        return 0;
    }

    直接插入(稳定):拿到一张新牌,从后往前看;大于新牌,则往后移一位;小于或等于,则将新牌插入到后一位;

    #include <iostream>
    using namespace std;
    //直接插入排序算法描述:
    /*
    1、第一层循环:拿到元素。
    2、第二层循环:从该元素的前一个位置开始,一直向前循环,若大于拿到的元素,则向后移一位;若小于该元素,则把该元素插入到后面一位的位置上
    3、重复做以上动作,直至最后一个元素也插好了。
    */    //==》O(n^2)
    void InsertSeq(int a[],int len)
    {
        for(int i=0;i<len;i++)
        {
            int tmp = a[i];
            int j=i-1;
            while(j>=0 && a[j] > tmp)
            {
                a[j+1]=a[j];
                j--;
            }
            a[j+1]=tmp;
        }
        return; 
    }
    
    int main()
    {
        int a[]={12,8,20,5,9,16,7,30};
        int len=sizeof(a)/sizeof(a[0]);
        InsertSeq(a,len);
        for(int i=0;i<len;i++)
        {
            cout<<a[i]<<" ";
        }
    }

    ==》改进1:二分插入排序(稳定)

    代码:

    #include <iostream>
    using namespace std;
    //直接插入排序的改进算法——二分查找定位插入算法描述:
    /*
    1、第一层循环:拿到元素。
    2、二分法定位插入位置(插入改位置的后面)
    3、把定位后右面的元素   从后往前    依次向后移动一位。
    4、把拿到的元素插进去
    */    //==》O(n^2)
    void DivInsertSeq(int a[],int len)
    {
        for(int i=0;i<len;i++)
        {
            int tmp = a[i];
            int left=0;
            int right=i-1;
            while(left<=right)
            {
                int mid=(left+right)/2;
                if(a[mid]>tmp)
                    right=mid-1;
                else
                    left=mid+1;
            }
            for(int j=i-1;j>left;j--)
            {
                a[j+1]=a[j];
            }
            a[left]=tmp;
        }
        return; 
    }
    
    int main()
    {
        int a[]={12,8,20,5,9,16,7,30};
        int len=sizeof(a)/sizeof(a[0]);
        DivInsertSeq(a,len);
        for(int i=0;i<len;i++)
        {
            cout<<a[i]<<" ";
        }
        return 0;
    }

     ==》改进2:希尔排序(不稳定)

    O(nlogn)

    归并(稳定)

    快排(不稳定)

    堆排(不稳定)

  • 相关阅读:
    DIOCP开源项目详解编码器和解码器和如何在传输中加入压缩和解压功能
    DIOCP开源项目DEMO(怎么样操作远程数据库)
    网站文件更新工具
    使用Javascript正则表达式来格式化XML内容
    加载有命名空间,但没有声名的XML
    使用参数化和块语句来提高批处理SQL语句的执行效率
    让Dotnet识别Java发送来的自定义SoapHeader
    中行的EToken
    异步调用方法时异常的捕获
    使用参数化和块语句来提高批处理SQL语句的执行效率(2)
  • 原文地址:https://www.cnblogs.com/westlife-11358/p/9318790.html
Copyright © 2011-2022 走看看