zoukankan      html  css  js  c++  java
  • 排序算法汇总

    一.排序算法

    1.直接插入排序

          算法思想:直接插入排序是利用顺序查找来确定r[i]在r[1..i-1]有序序列区中插入的位置,将第i个记录的关键字Ki与前面记录r[1]~r[i-1]的关键字从后面向前顺序进行比较,将所有关键字大于Ki的记录依次向后移动一个位置,知道遇到一个关键字小于或等于Ki的记录,该记录的位置即为r[i]的位置。

         c语言代码如下:

     1 void InsertSort(RecordList L)
     2 {
     3     for(int i=2;i<=L.length;i++)
     4     {
     5         if(L.r[i].Key<L.r[i-1].key)
     6         {
     7             L.r[0] = L.r[i];          //监视哨备份待查记录
     8             for(j=i-1;L.r[0].key<L.r[j].key;j--)
     9                 L.r[j+1] = L.r[j];  //记录后移
    10                 L.r[j+1]=L.r[0];  //插入到正确的位置
    11 
    12         }
    13     }
    14 }
    View Code

         java语言实现:

     1 public class InsertSort {
     2     public static void main(String[] args) {
     3        int [] arr = new int[]{4,5,2,1,0,3,2,5,7,98,0,12,34,6,7,4};
     4        insertSort(arr);
     5         for (int i = 0; i < arr.length; i++) {
     6             System.out.println(arr[i]);
     7         }
     8     }
     9     public static void insertSort(int [] arr){
    10         for (int i = 1; i < arr.length; i++) {
    11             if(arr[i] < arr[i - 1]){
    12                 int temp = arr[i];
    13                 for (int j = i ; j >= 0; j--) {
    14                     if(temp < arr[j]) {
    15                         arr[j + 1] = arr[j];
    16                         arr[j] = temp;
    17                     }
    18                 }
    19             }
    20         }
    21     }
    22 }

          时间复杂度:在最坏情况下(倒序)时间复杂度为O(n^2)。

          空间复杂度:它只需要一个元素的辅助空间,即监视哨r[0],用于元素位置的交换,所以空间复杂度为O(1)。

          稳定性:插入排序是稳定的,因为具有相同值得元素必然插在同一值得前一个元素的后面。

    2.折半插入排序

          算法思想:此算法思想与直接插入算法思想类似,将直接插入法每次折半后,再进行插入。

          c语言代码如下:

     1 void BiInsertSort(RecordList L)
     2 {
     3   for(int i=2;i<L.length;i++)
     4     {
     5       L.r[0] = L.r[i];  //监视哨备份待查记录
     6       if(L.r[i].key>L.r[i-1].key)
     7         {
     8           low=1; high=1; //折半查找r[i]的位置
     9           while(low<high)
    10             {
    11               mid = (low+high)/2;
    12               if(L.r[i].key<L.r[mid].key)
    13                   high=mid-1;
    14               else low=mid+1;
    15             }
    16             for(j=i-1;j>=low;j-)
    17                 L.r[j+1] = L.r[j];//记录后移
    18             L.r[low]=L.r[0];//插入正确的位置
    19         }
    20     }
    21 }
    View Code

           时间复杂度:O(n^2)

           空间复杂度与稳定性和直接插入法一致。

    3.希尔排序

          算法思想:先将整个待排的序列分割成若干个子序列,分别进行插入排序,然后依次缩减增量再进行排序,待整个序列中元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。

          c语言代码如下:

     1 void shellInsert(RecordList L,int dk)
     2 {
     3     for(i=dk+1;i<=L.length;i++)
     4         if(L.r[i].key<L.r[i-dk].key)
     5         {
     6             L.r[0] = L.r[i];
     7             for(j=i-dk;j>0&&(L.r[0].key<L.r[j].key);j-=dk;)
     8             L.r[j+dk] = L.r[j];
     9             L.r[j+dk]=L.r[0];
    10         }
    11 }
    12 void ShellSort(RecordList L,int dlta[],intt)
    13 {
    14     for(k=0;k<L.length;t++)
    15         shellInsert(L,dlta);
    16 }
    View Code

         时间复杂度:O(n^2)

         空间复杂度与直接插入法一致,只需要一个辅助空间。

         稳定性:在排序过程中两个相同的关键字可能发生顺序的改变,所以不稳定。

    4.冒泡排序法

         算法思想:对待排序的记录的关键字两两进行比较,只要发现两个记录为逆序之后进行交换,知道没有逆序为止。

         C语言代码如下:

     1 void BubbleSort(RecordList L)
     2 {
     3   flag = 1;
     4   for(int i=1;i<L.length-1&&flag;i++)
     5     {
     6       flag=0;
     7       for(j=1;j<L.length-i;j++)
     8          if( L.r[j].key>L.r[j+1].key)
     9          }
    10              t=L.r[j];
    11              L.r[j]=L.r[j+1];
    12              L.r[j+1] = t;
    13              flag=1;
    14          {
    15          
    16     }
    17 }
    View Code

       时间复杂度:O(n^2)

       空间复杂度:需要一个辅助空间进行交换,为O(1)。

    5.快速排序法

        算法思想:从待排序列中任意选择一个记录,以该记录的关键字作为“枢轴”,凡是关键字小于枢轴的记录均移动至该记录之前,反之凡是关键字大于轴枢的记录均移至该记录之后。

        c语言代码如下:

     1 一趟排序
     2 int QKpass(RecordList L,int low,int high)
     3 {
     4     L.r[0]=L.r[low];
     5     while(low<high)
     6     {
     7         while(low<high&&L.r[high].key>=L.r[0].key) --high;
     8         L.r[low] = L.r[high];
     9         while(low<high&&L.r[low].key<=L.r[0].key) ++low;
    10         L.r[high] = L.r[low];
    11     }
    12     L.r[low]=L.r[0];
    13     return low;
    14 }
    15 //快速排序
    16 void QKSort(RecordList L,int low,int high)
    17 {
    18     if(low<high)
    19     {
    20         pos=QKpass(L,low,high);
    21         QKSort(L,low,pos-1);
    22         QKSort(L,pos+1;high);
    23     }
    24 }
    View Code

        时间复杂度:最坏情况下:O(n^2)

                              最好情况下:T(n)=θ(nlogn)

        空间复杂度:快排总共需要分割log2n次,即需要log2n个辅助空间记录枢轴的位置,所以复杂度为O(log2n)。

        稳定性:不稳定。

    6.简单选择排序法

        算法思想:从第一个记录开始,将后面n-1个记录进行比较,找到最小的和第一个记录交换,从第二个记录开始,重复以上步骤。

        c语言代码如下:

     1 void sellectSort(RecordList L)
     2 {
     3     for(int i=1;i<L.length;i++)
     4     {
     5         k=i;
     6         for(j=i+1;j<L.length;j++)
     7             if(L.r[j]<L.r[i])
     8             k=j;
     9         if(k!=i)
    10         {
    11             t=L.r[i];
    12             L.r[i]=L.r[k];
    13             L.r[k]=t;     
    14         }
    15     }
    16 }
    View Code

         时间复杂度:O(n^2)

         空间复杂度:需要一个辅助空间进行交换,故为O(1).

    7.堆排序

         算法思想及步骤:

            ①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2) 其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。
            ②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。
           ③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)[2] 
          c语言代码:
     1 void HeapSort(RecordList L)
     2 {
     3     CreatHeap(L);
     4     for(i=L.length;i>=2;i--)
     5     {
     6         L.r[0]=L.r[1];
     7         L.r[1]=L.r[i];
     8         L.r[i]=L.r[0];
     9     }
    10 }
    11 //建初始堆
    12 void CreatHeap(RecordList L)
    13 {
    14     for(i=L.length/2;i>=1;i--)
    15         HeapAdjust(L,i,L,length);
    16 }
    17 //堆的筛选
    18 void HeapAdjust(RecordList L,int s,int m)
    19 {
    20     t=L.r[s];
    21     for(j=2*s;j<=m;j*=2)
    22     {
    23         if(j<m&&L.r[j].key>L.r[j+1].key)
    24             j++;
    25         if(t.key<=L.r[j].key)
    26             break;
    27         L.r[s]=L.r[j];
    28         s=j;
    29     }
    30     L.r[s]=t;
    31 }
    View Code

         时间复杂度:O(nLog2n)

         空间复杂度:O(1)

         稳定性:不稳定。

    8.桶排序

         桶排序的前提条件:必须知道待排的数据的范围。有以下两种情况:

       (1)待排数据大小的范围比较小的情况,例如:有5个待排的序列(a[4,7,9,4,3]),每个数字的大小都在0~10之间.

         算法思想:创建10个桶,即大小为10的一维数组b,初始化为0,依次遍历原数组(4,7,9,4,3),将遍历的每个数字对应下标的数组值加1(例如:遍历第一个数字为4,则b[4]+1;第二个数为7,则b[7]+1;.....)最后得到数组内b[3]=1;b[4]=2;b[7]=1;b[9]=1;最后将b数组打印出来就是所排的序列(例如:b[3]=1,则打印一个3,b[4]=2打印两个4)。

         c语言代码如下:

     1 void TSort(int a[], int n)
     2 {
     3     int t=0;
     4     int b[k] = {0};    //k为桶的个数,自行定义
     5     for (int i = 0; i< n; i++)
     6     {  
     7         t = a[i];
     8         b[t]++;
     9     }
    10     for (int i = 1; i< 10; i++)
    11      for (int j = 1; j <= b[i]; j++)
    12         printf("%d ", i);
    13 }
    View Code

        (2)待排数据范围比较大的情况,例如有20个待排数据,每个数据的范围为0~999,那么如果按照上面的方法,则需要创建999个桶,能用到的桶<=20,显然不是最优算法,那么就需要第二种解法:

          算法思想:创建10个桶即创建大小为10 的一维数组,进行三次桶排:

          第一次:将20个数的元素本身依次放入个位数对应下标的数组中(例如:将123放入b[3]中)每个桶中可能有多个数。

    再讲20个数字依次存入原来的数组中。

          第二次:将第一次排好的数组中的20个数的元素本身依次放入十位数对应下标的数组中(例如:将123放入b[2]中)每个桶中可能有多个数,再讲20个数字依次存入原来的数组中。

         第三次:将第二次排好的数组中的20个数的元素本身依次放入百位数对应下标的数组中(例如:将123放入b[1]中)每个桶中可能有多个数,再讲20个数字依次存入原来的数组中。即已经排序好。

  • 相关阅读:
    四大组件之内容提供者
    【风马一族_代码英语】英语学习
    利用Maven快速创建一个简单的spring boot 实例
    Maven项目下面没有src/main/java这个包
    Maven中,pom.xml文件报错
    Maven一:maven的下载和环境安装以及创建简单的Maven项目
    SpringMVC
    自动装箱、拆箱
    序列化:Serializable
    java反射机制出浅读
  • 原文地址:https://www.cnblogs.com/xyzyj/p/6623214.html
Copyright © 2011-2022 走看看