zoukankan      html  css  js  c++  java
  • 几大常用排序算法

    1.  插入排序

       算法原理:从整个待排序列中选出一个元素插入到已经有序的子序列中去,得到一个有序的、元素加一的子序列,直到整个序列的待插入元素为0,则整个序列全部有序。

       具体的实现的时候,我们一般选择第一个元素作为有序的序列,将后面的元素插入到前面有序的序列直到整个序列有序。

       时间复杂度:插入排序在最好情况下,需要比较n-1次,无需交换元素,时间复杂度为O(n);在最坏情况下,时间复杂度为O(n2)。

       

       代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int len=15;
    int main()
    {
        int a[len]={1,87,64,19,53,14,57,62,23,37,48,9,91,45,81};
        for(int i=1;i<len;i++)
        {
            int j=i;
            int temp=a[i];
            while(j>0)
            {
                if(a[j-1]<a[i])//找到第一个比它小的数的位置
                {
                    for(int k=i;k>j;k--)//比它大的数全部后移
                        a[k]=a[k-1];
                    a[j]=temp;//将数值附到该位置上
                    break;
                }
                j--;
            }
        }
        for(int i=0;i<len;i++)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }

     2.  选择排序

       算法原理:为每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止。

       算法步骤

       1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

       2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

       3)重复第二步,直到所有元素均排序完毕。  

       时间复杂度:无论数组原始排列如何,比较次数是不变的;对于交换操作,在最好情况下也就是数组完全有序的时候,无需任何交换移动,

       在最差情况下,也就是数组倒序的时候,交换次数为n-1次。综合下来,时间复杂度为O(n2)

       代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int len=15;
    int main()
    {
        int a[len]={1,87,64,19,53,14,57,62,23,37,48,9,91,45,81};
        for(int i=0;i<len-1;i++)
        {
            int temp=i;
            for(int j=i+1;j<len;j++)
            {
                if(a[temp]>a[j])
                    temp=j;
            }
            if(temp!=i)
                swap(a[temp],a[i]);
        }
        for(int i=0;i<len;i++)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }

    3.  冒泡排序

       算法思想:比较相邻的元素。如果第一个比第二个大,就交换他们两个。

       对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

       针对所有的元素重复以上的步骤,除了最后一个。

       持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

       时间复杂度分析:最优时间O(n),最差时间O(n^2)。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int len=15;
    int main()
    {
        int a[len]={1,87,64,19,53,14,57,62,23,37,48,9,91,45,81};
        for(int i=0;i<len-1;i++)//进行几轮比较,确定位置
        {
            bool flag=false;//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已然完成。
            for(int j=0;j<len-1-i;j++)
            {
                if(a[j]>a[j+1])
                {
                    swap(a[j],a[j+1]);
                    flag=true;
                }
            }
            if(flag==false)
                break;
        }
        for(int i=0;i<len;i++)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }

    4.  归并排序

       思想:是利用递归与分治的技术将数据序列划分为越来越小的半子表,再对半子表排序,最后再用递归方法将排好序的半子表合并成越来越大的有序序列。

       时间复杂度:O(nlogn)

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int a[20]={5,6,9,15,4,-1,-9,5,-6,71,5,-36,2,15,48,-15,14,6,9,11};
    int l,r;
    void mergee(int l,int m,int r)
    {
        int T[20];
        int i=l,j=m+1;
        int k=0;
        while(i<=m&&j<=r)
        {
            if(a[i]<=a[j])
                T[k++]=a[i++];
            else
                T[k++]=a[j++];
        }
        while(i<=m)
            T[k++]=a[i++];
        while(j<=r)
            T[k++]=a[j++];
        for(int i=0;i<k;i++)
            a[l+i]=T[i];
    }
    int mergr_sort(int l,int r)
    {
        if(r-l>0)
        {
            int mid=(l+r)/2;
            int p=l,q=mid,i=l;
            mergr_sort(l,mid);
            mergr_sort(mid+1,r);
            mergee(l,mid,r);
        }
    }
    int main()
    {
        scanf("%d %d",&l,&r);
        mergr_sort(l,r);
        for(int i=0;i<20;i++)
            printf("%d ",a[i]);
        printf("
    ");
        return 0;
    }

    5.  快速排序

       通过一轮的排序将序列分割成独立的两部分,其中一部分序列的关键字(这里主要用值来表示)均比另一部分关键字小。继续递归的对长度较短的序列进行同样的分割,最后到达整体有序。为了实现一次划分,我们可以从数组(假定数据是存在数组中)的两端移动下标,必要时交换记录,直到数组两端的下标相遇为止。为此,我们附设两个指针(下角标)i 和 j, 通过 j 从当前序列的有段向左扫描,越过不小于基准值的记录。当遇到小于基准值的记录时,扫描停止。通过 i 从当前序列的左端向右扫描,越过小于基准值的记录。当遇到不小于基准值的记录时,扫描停止。交换两个方向扫描停止的记录 a[j] 与 a[i]。 然后,继续扫描,直至 i 与 j 相遇为止。它的平均时间复杂度为O(nlogn)

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int len=15;
    int a[len]={1,87,64,19,53,14,57,62,23,37,48,9,91,45,81};
    void quicksort(int l,int r)
    {
        if(l>r)
            return;
        int temp=a[l];
        int i=l;int j=r;
        while(i!=j)
        {
            while(a[j]>=temp&&i<j)
                j--;/*为什么要从右边,因为我们选择的基数是从左边开始选择的,开始的方向必须是要从基数的对面开始,
    如果你要从左边开始找那么选择基数的时候就从右边的数作为基数*/
    while(a[i]<=temp&&i<j) i++; if(i<j) swap(a[i],a[j]); } a[l]=a[i]; a[i]=temp; quicksort(l,i-1); quicksort(i+1,r); } int main() { quicksort(0,14); for(int i=0;i<len;i++) printf("%d ",a[i]); printf(" "); return 0; }

     

  • 相关阅读:
    Python selenium —— 父子、兄弟、相邻节点定位方式详解
    Python爬虫入门教程石家庄链家租房数据抓取
    自动化测试 selenium 环境搭建
    python3爬虫(find_all用法等)
    python网络爬虫抓取动态网页并将数据存入数据库MySQL
    mvc设计模式和mvc框架的区别
    python正则表达式贪婪与非贪婪模式
    python3获取一个网页特定内容
    使用exceljs 前端导出表格并自定义样式和超链接
    如何在devtools中找到未使用 JavaScript 和 CSS 代码
  • 原文地址:https://www.cnblogs.com/jkzr/p/10384343.html
Copyright © 2011-2022 走看看