zoukankan      html  css  js  c++  java
  • 排序算法总结(一)

    查找和排序是计算机应用中较为基础同时也很重要的两个组成成分。特别是当今网络如此盛行,Internet上充斥着各种各样的数据,图片,文本,音视频等,用户如何搜寻自己想要的数据,服务者如何及时有效的将用户的需求返回,都需要这些基础算法的帮助。在本人复习数据结构的时候,特意结合网上各位大牛的神贴,以及自己的一些理解,整理了一下一些常用的查找和排序算法,如有雷同之处,请各位大牛多多包涵。

     

    基于比较的算法:

    1. 选择排序

        在众多的排序算法中,选择排序应该是最容易理解的一个算法了。其平均时间复杂度为O(n^2),空间复杂度则是O(1), 并且选择排序是不稳定的排序(值相同的两个元素在排序之后相互位置可能发生变化)。

        选择排序是一个递归的查找比较算法:

              (1)遍历一次尚未排序的数组元素,找到其中最大的元素,

              (2)将其与尚未排序的数组最后一个元素互换

              (3)将找到的最大元素从未排序的数组元素中取出

              (4)其余未排序数组元素,重复操作(1),直到未排序数组中没有剩余元素。

     1 void insertion_sort(int a[],int length)
     2 {
     3      for(int i=length -1; i>0;i--)
     4      {
     5          int maxData = a[i];
     6          int index =0;
                // 寻找最大元素
     7          for(int j=0;j<i;j++)
     8          {
     9              if(maxData < a[j])
    10              {
    11                  maxData = a[j];
    12                  index =j;
    13              }
    14          }
                // 是否需要交换位置
    15          if(maxData != a[i])
    16          {
    17            swap(a[i],a[index]);
    18          }
    19      }
    20 }
    selection_sort

                    

    2. 冒泡排序

        冒泡排序也是一个比较基础的排序算法,基于比较。其平均时间复杂度为O(n^2), 空间复杂度O(1), 稳定的排序。

        冒泡排序算法的运作如下: (此处参考百度百科,冒泡排序的介绍:http://baike.baidu.com/link?url=JVltAqLpNLpQuk7LR1CnJGykNKTr1jYFWoDSj1vBuZPVXzQ8gC5JUOYnoFOSixWF)

     

         (1) 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
         (2) 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
         (3) 针对所有的元素重复以上的步骤,除了最后一个。
         (4) 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 
     1 void bubble_sort(int a[],int length)
     2 {
     3      for(int i=0;i<length -1; i++)  // 外层循环为需要递归的次数 
     4      {
     5          for(int j = 0; j<length -i -1; j++) // 内层循环用于调整相邻节点的位置 
     6          {
     7                  if(a[j]>a[j+1])
     8                     swap(a[j],a[j+1]);
     9          }
    10      }
    11 }
    bubble_sort

       需要指出的是,在冒泡排序中,往往不需要进行n-1次调整,数组就可能已经是有序的了,这时候继续比较就显得比较浪费,而且效率也低。通常的做法是在内循环中加入一个哨兵标志,如果当前循环中没有相互交换的元素,则认为数组已经有序,可以结束排序,其运作如下:

         (1) 比较相邻的元素。如果第一个比第二个大,就交换他们两个,进入步骤(2) 
         (2) 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
         (3) 针对所有的元素重复以上的步骤,除了最后一个。如果上面的比较中没有出现交换操作,算法退出。否则,进入步骤(4).
         (4) 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 

     其实现如下:

     1 void supper_bubble_sort(int a[],int length)
     2 {
     3      for(int i=0;i<length -1; i++)  // 外层循环为需要递归的次数 
     4      {
     5          bool sorted =false; 
     6          for(int j = 0; j<length -i -1; j++) // 内层循环用于调整相邻节点的位置 
     7          {
     8                  if(a[j]>a[j+1])
     9                  {
    10                     swap(a[j],a[j+1]);
    11                     sorted = true;  // 本次循环过程中,出现了交换 
    12                  }
    13          }
    14          if(sorted == false)  // 本次过程中没有出现数据交换,算法提前结束 
    15              break;
    16      }
    17 }
    supper_bubble_sort

    3. 插入排序

        相对比较基础的一个排序算法。 莫非大牛们都比较喜欢“斗地主”,为嘛都拿打扑克来做例子!!(不过确实很形象~)

        这个算法呢,理解起来比较容易,不过写程序的时候,因为移位操作比较多,在边界条件的选择上往往容易出问题。

        要注意从数组起始位置开始查找,还是数组最后记录的位置。

        算法的时间复杂度也是0(n^2),空间复杂度O(1),稳定的排序。

     1 /**************************************
     2  * Insertion_sort
     3  * 每次从已插入的数组最后一个元素开始比较,
     4  * 如果新的元素比最后一个元素大,则直接放入
     5  * 已排序队列的最后位。否则,将新元素与当前
     6  * 元素互换位置递归查找,直到找到第一个比新
     7  * 元素小的元素,并将新的元素插入到该位置 
     8 **************************************/
     9 void Insertion_sort(int a[],int length)
    10 {
    11      for(int i =1;i<length; i++)
    12      {
    13           int key = a[i];
    14           int j=i -1;
    15           while(j>=0 && a[j]>a[j+1])
    16           {
    17              swap(a[j],a[j+1]); // 循环移位操作 
    18              j--;
    19           }
    20           if(a[j]>key) //插入新元素 
    21             a[j] = key;
    22      }
    23 }
    insertion_sort

    4. 希尔排序

        希尔排序又称“缩小增量排序”,从本质上来说,依旧是插入排序,因此希尔排序也可以叫做分组插入排序。不过希尔排序的效率比简单的插入排序则要高很多。

        tips:希尔排序的一大特点是,通过增量,将数组分割成对应大小的子序列,每次并不是对所有的元素进行插入排序,而只是对各个子序列进行排序。

        由于增量是逐个减小的,那么对应的各个子序列的大小则是从小变大的。而当某一趟排序后,进行下一次排序的时候,每个子序列中已经排好序的元素都会增加,从而可以减少由插入较小元素而导致的数据移动,进而提高排序的效率。

        tips: 对于希尔排序来说,增量的选择对于排序的效率影响很大,如果选择合适的增量作为每次的分组依据显得尤为重要。这里没有一个统一的标准,但是需要保证最后一次的增量为1.

  • 相关阅读:
    七月二十六学习报告
    学习笔记167—circos 可视化手册【fonts 篇】
    学习笔记166—Circos增加区块属性【highlight 属性】
    学习笔记165—Circos入门总结【for Brain Network】
    iOS 逆向工程(十三)之加壳与脱壳/砸壳
    iOS 逆向工程(十二)之class-dump工具使用
    iOS 逆向工程(十一)之Reveal工具使用
    iOS 逆向工程(十)之Cytript通用语法
    iOS 逆向工程(九)之解决iOS终端的中文乱码
    iOS 逆向工程(八)之sh脚本文件处理重复性工作
  • 原文地址:https://www.cnblogs.com/double-win/p/3598573.html
Copyright © 2011-2022 走看看