排序算法

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。
记住时间算法度 是指代码要执行的次数,取最高次方,去除系数
1)比较排序:
  1.选择排序 n + n-1 + n-2 + … + 2 + 1 = n * (n+1) / 2 = 0.5 * n ^ 2 + 0.5 * n,那么时间复杂度是O(N^2),这是雷打不动的时间复杂度
    每一趟进行选择出最大值或最小值,然后进行交换首末位置,每趟减少一个
    时间复杂度无论什么时候都是o(n^2),因为它是数据规模为n,然后每趟选出最大值或最小值,进行n趟;

2.冒泡排序
  冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,
  如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,
  也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
  时间复杂度最优为o(n),已经排序好的可以用flag来通过n次比较直接结束排序 最差为o(n^2)

3.插入排序
  插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。
  它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,
  通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,
  需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
  时间复杂度:最佳为o(n):因为如果是已经排序好的序列话,它每次只需和前面已排序好的序列比较一次,总共比较n次,也是可以通过flag实现的,然后最差时间复杂度为o(n^2)

4.希尔排序(它是第一个时间复杂度冲破o(n^2)的)
  它是以插入排序为基础建立的,
  它的工作原理为:使用增量对序列进行分组进行插入排序,希尔建议的增量(希尔增量):{n/2,(n/2)/2......1},但不是最优的
  比如一个序列的长度为10,也就是一开始分为5组,然后2组,直到分为1组时.
  它的时间复杂度无论什么时候都为o(nlog2n)

5.归并排序:
  归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。
  将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
  最佳情况:T(n) = O(n) 最差情况:T(n) = O(nlogn) 平均情况:T(n) = O(nlogn)
2-路归并的具体解析:
  1)将序列分成左右子序列
  2)再将左右子序列分成左右子序列,直至分成子序列都小于2
  3)将左右子序列进行排序后归并到一起在进行归并排序
  补充:需要额外的空间

6.快速排序:
  快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
我的解析:
  1)先将第一个数为基准,然后以这个数为基准进行选择排序,将小于此数的组成一个序列,
  2)一轮比较完成后,将此基准数与小于此数的序列最后一个进行替换
  3)然后得到此基准左边全是小于它的,右边全是大于它的
  4)然后对左边的数列重复1-3步骤,
  5)右边在根据1-3步骤在比较排序
  时间复杂度最优为O(nlog2n),最差为O(n^2),平均为O(long2n)
7.堆排序:
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
我的理解:
前提:
堆:(具有特定性质的完全二叉树)
  1)每个结点的值都大于或等于左右孩子结点的值,称为大顶堆;
  2)每个结点的值都小于或等于左右孩子结点的值,称为小顶堆;

  1)先将待排序的序列构建成堆(完全二叉树)
  2)然后根据情况构建大顶堆(升序)或者小顶堆(降序)
  3)然后将根元素与末尾元素进行交换
  4)然后将末尾元素剔除进数组的末尾
  堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,时间复杂度均为O(nlogn),是不稳定排序

2)非比较排序:
1.计数排序:
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
算法描述:
  1)先找出此数列的最大值i
  2)申明出长度为i的数组c
  3)统计每个值为i的元素出现的次数,并存入数组c的i项中
  4)反向填充目标数组
时间复杂度都为:O(n+k):k为数列中的最大值


2.桶排序:
桶函数是计数函数的升级版,它利用了函数的映射关系
算法描述:
  1)设置桶的数量为n
  2)通过最大值和最小值判断每个桶的数值范围大小m=(max-min)/n
  3)通过将每个值放进不同的桶中,(每个桶都有具体的数值范围:比如第一个桶为:最小值+m)
  4)然后可以对每个桶在进行桶排序或者其他排序
  5)然后将排序好的桶,进行合并
桶排序最好情况下使用线性时间O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,
因为其它部分的时间复杂度都为O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。
最佳情况:T(n) = O(n+k) 最差情况:T(n) = O(n+k) 平均情况:T(n) = O(n^2)  

3.基数排序:
基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn),为数组长度,k为数组中的数的最大的位数;
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,
先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。
算法描述:
它是根据序列里的值的每位数字来分配桶
分为两种:
  1.MSD:从高位开始排序
  2.LSD:从低位开始排序
  1)先从序列中取出最大值,并取得位数n(比如123就为3位)
  2)从第一位开始对序列进行计数排序(只看当前排序的位)
  3)一直到第n位.
它的算法时间复杂度都为O(n*k):k为最大值的位数

原文地址:https://www.cnblogs.com/nyhhd/p/12546268.html