• [排序算法总结]冒泡排序、简单选择排序


      排序是日常生活中最常见的操作,也是算法中最有趣的问题之一,排序问题可以描述为:

      输入:n个数<a1,a2,…,an>

      输出:输入序列的一个排列(即重新排序)<a1’,a2’,….,an’>,使得a1’<=a2’<=…<=an’。

      待排序的数也称为关键字(key)。

           本篇文章将列举出常见的排序算法,分别从思想、复杂度、稳定性等方面,总结其优劣和适用情形,并给出源码示例。

      要想解决排序问题,最直观也是最简单的做法就是两两比较,每次找出当前最大(最小)的,直至整个排序完成。这种算法有一个比较形象的的名字叫“冒泡法”。

    一、冒泡排序BubbleSort):

      思想:

      冒泡排序的是第一次通过两两比较,找出a1-an中最大的数,并将其放在an的位置,然后第二次执行同样的操作,找出a1-an-1中最大的数,放在an-1的位置,如此下去,直至待排序集合只剩一个数。

      代码:

      输入:n个元素的数组A[0…n-1]

      输出:按非降序排列的数组A[0…n-1](下同)

     1 void BubbleSort(int A[],int length)
     2 
     3 {
     4 
     5      for(int i=1; i<length; i++)
     6 
     7      {
     8 
     9              for(int j=1; j<=length-i; j++)
    10 
    11              {
    12 
    13                      if(A[j-1]>A[j])
    14 
    15                      {
    16 
    17                           swap(A[j-1],A[j]);                    
    18 
    19                      }       
    20 
    21              }       
    22 
    23      }    
    24 
    25 }
    View Code

      复杂度:

      不难看出,排序的基本运算是比较操作,当待排序数组长度为n时,比较操作执行的次数是(n-1)+(n-2)+…+1即n(n-1)/2,故其时间复杂度是O(n2)的。至于空间复杂度,冒泡排序无需申请额外的空间。

      稳定性:

      由算法过程不难看出,冒泡排序不会打乱相同数的原顺序,因此是稳定的。

      改进:

      算法的外层循环是扫描次数,内层循环是不停对当前待排序数组进行排序,当执行到某次扫描后,数组可能已经是有序的,但是外层循环还是会继续执行,因此,改进的动机便是,当数组已是有序时,即退出排序。判断是否有序的依据便是是否执行了交换操作。因此,改进后的代码如下:

     1 void BubbleSort(int A[],int length)
     2 
     3 {
     4 
     5 bool sorted = false;
     6 
     7      for(int i=1; i<length&&!sorted; i++)
     8 
     9      {       sorted = true;
    10 
    11              for(int j=1; j<=length-i; j++)
    12 
    13              {
    14 
    15                      if(A[j-1]>A[j])
    16 
    17                      {
    18 
    19                           swap(A[j-1],A[j]);  
    20 
    21                                                    sorted = false;                 
    22 
    23                      }       
    24 
    25              }       
    26 
    27      }    
    28 
    29 }
    View Code

    二、简单选择排序(SelectionSort):

      思想:

      简单选择排序是对冒泡排序的一种改进,冒泡排序每次都会执行两两交换,不停“吐泡”,目的就是为了让最大的数,能够到当前的最后位置。这中间执行了很多多余的交换操作。简单选择排序是每次找出当前最大的数,放到数组最后,即第一次执行时,找出a1-an中最大的数放到an的位置,在找出a1-an-1中最大的数,放到an-1的位置,直至待排序集合只剩一个数。

      不难看出,以上算法过程是一个归纳的过程,因此选择排序也很容易转换成递归版本的算法。

      代码:

      非递归版本:

     1 //返回最大的那个数的位置
     2 
     3 int SelectMaxKey(int A[],int offset)
     4 
     5 {
     6 
     7      int MAX = INT_MIN;
     8 
     9      int pos=0;
    10 
    11      for(int i=0; i<=offset; i++)
    12 
    13      {
    14 
    15           if(A[i]>MAX){
    16 
    17                MAX = A[i];
    18 
    19                pos = i;            
    20 
    21           }
    22 
    23      }
    24 
    25      return pos;    
    26 
    27 }
    28 
    29  
    30 
    31 void SelectionSort(int A[],int length)
    32 
    33 {
    34 
    35      int temp;
    36 
    37      for(int i=1; i<length; i++)
    38 
    39      {
    40 
    41            temp = SelectMaxKey(A,length-i);
    42 
    43            if(temp!=length-i)
    44 
    45                swap(A[temp],A[length-i]);         
    46 
    47      }    
    48 
    49 }
    View Code

      递归版本

     1 void SelectionSortRec(int A[],int offset,int length)
     2 
     3 {
     4 
     5      int k;
     6 
     7      if(offset<length-1)
     8 
     9      {
    10 
    11           k = offset;
    12 
    13           for(int j=offset+1; j<length; j++)
    14 
    15           {
    16 
    17                   if(A[j]<A[k]) k = j;       
    18 
    19           }                  
    20 
    21           if(k!=offset)
    22 
    23                   swap(A[k],A[offset]);
    24 
    25           SelectionSortRec(A,offset+1,length);
    26 
    27      }
    28 
    29 }
    View Code

      复杂度:

      简单选择排序是对冒泡排序的一种改进,减少的只是交换操作,比较操作并没有减少,因此,其时间复杂度也是O(n2),选择排序同样无需申请额外空间。

      稳定性:

      当当前排序数组中有两个最大的数时,由于在找最大数时,是使用的if(A[i]>MAX)判断,因此,总会把先遇到的那个最大的数放到数组最后,因此打乱了原来的顺序,从这个角度上看,简单选择排序是不稳定的。当然,如果判断使用if(A[i]>=MAX),那么每次总是找最大的数中的最后一个放到数组最后,此时并没有打乱原顺序,此时又可以说是稳定的。

      接下来《排序算法总结》系列将带来插入排序和归并排序讲解。以上如有任何错误或表述不清楚的,欢迎指出。

  • 相关阅读:
    Ceph 之RGW Cache
    Ceph 之RGW Pub-Sub Module
    Ceph 之RGW Data Layout
    RocksDB 之Write Ahead Log(WAL)
    Ceph 之 Background on http frontends
    Ceph 之Multisite 下的bucket reshard
    Ceph之PG数调整
    Ceph之对象存储网关RADOS Gateway(RGW)
    window mysql重启、忘记密码等操作
    selenium处理HTML5视频播放未能自动播放解决办法
  • 原文地址:https://www.cnblogs.com/codershell/p/3301825.html
Copyright © 2020-2023  润新知