排序算法学习(一)

来源:互联网 发布:windows svn 备份恢复 编辑:程序博客网 时间:2024/06/05 18:59

排序算法

按种类分为内部排序和外部排序。

内部排序是指,数据完全可以在内存中完成排序。

外部排序是指,数据太大,需要一部分一部分读入内存就行排序。


外部排序的典型做法是,将数据分成若干合理大小数据段,先一段一段送入内存排序并存在硬盘中,然后再两两归并排序。其中两两合并,叫做两路排序。名称由来是,归并排序采用败者树算法,有几个叶子节点就是几路排序。需要额外内存空间。


内部排序:

插入排序:(直接插入排序,二分查找插入排序,希尔排序)

直接插入排序,第二个数据与第一个数据进行比较,小于第一个数则将第二哥数据插入第一个数据之前;第三个数据与第二个数据进行比较,若比第二个小,再比较第一个数据,若比较第一个数据大,插入第一个数据之后,否则插入第一个数据之前······递归····,时间复杂度最差(倒序数据)O(n^2),最好(有序数据)O(n),平均O(n^2)。 稳定。

二分查找排序是对直接插入排序的优化,优化的地方在于,可以减少比较的次数,最好情况复杂度为O(log2n).其余相同。

希尔排序是对直接插入排序的优化,优化的地方在于,将整个序列划分成若干组进行排序,再分别对子序列进行直接插入排序,使得原来序列成为基本有序。这样通过对较小的序列进行插入排序,然后对基本有序的数列进行插入排序,能够提高插入排序算法的效率。时间复杂度最好(有序数据)O(n),最坏O(nlog2n),平均O(nlog2n)。

在直接插入排序中,插入操作是通过逐个移动元素位置实现的。

               NOTE:一个排序算法的稳定与否,是看未排序前,相同数据的相对次序在经过该排序算法排序后,是否会发生改变。改变则不稳定,否则稳定。稳定性的意义在于,是否需要排序算法的稳定性。比如,对于一个复杂对象的多个属性排序,对应 同一类别商品 的  价格  销量,  如果按价格排好序后,又想按销量排序,这时,对于相同销量的商品,其之前的价格顺序不会改变。这时如果对销量相同的商品要求价格顺序不改变,这样的情况下,排序算法的稳定性才有意义。

冒泡排序:

冒泡排序的核心思想是,比较相邻两元素,大的一方在前面的话,交换二者顺序,使大数在后,从头交换到序列尾部,则序列中最大的元素在序列尾部,这时一次扫描和比较,再从头进行扫描和两两元素比较交换,则第二大的元素在序列倒数第二的位置,重复该步骤,最终得到升序的序列。时间复杂度,最好O(n)最坏O(n^2),平均O(n^2)。

选择排序:

选择排序也是一种简单直观的排序算法。它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再

从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。时间复杂度,最好O(n^2)最坏O(n^2),平均O(n^2)。


归并排序:

归并排序的核心思想是,将一序列元素细分到每一个元素为一组,此时有n组,然后将两两合并排序,此时有n/2组,再两两合并排序,此时变成n/4组,最终
变成一组,即得到有序的序列。实现可分为:迭代法和非迭代法。前者对应着自顶向下分,然后逐层合并。后者则是直接从底层向上合并。时间复杂度,最好O(nlogn),最坏O(nlogn)
,平均O(nlogn)。

堆排序:

堆排序的核心思想是利用完全二叉树的数据结构进行排序。这个树的要求是每一个父节点(2i)的值都要大于其左右孩子(left:2i+1,right:2i+2)的值,或者都小于。
都大于或者都小于取决于排序是要按照升序还是降序。
具体过程为:构造初始树,将原序列构造成完全二叉树,并调整树内节点,使满足都大于的要求。
交换树顶元素和最后一个叶节点,然后调整树,使树满足结构要求。(NOTE:交换元素的目的是为了将最大值或最小值拿出,类似于冒泡排序)
重复上述步骤,直至只剩一个堆顶元素。
NOTE:编程时,需要注意,再调整完底层父节点之后,然后就是调整上一层父节点,这时要注意,上一层父节点的调整可能导致,原来调整好的父节点,
又不符合要求了(可能得到上一层父节点的较小值),所以需要再进行原来层父节点的调整,可以用递归或循环。
时间复杂度:都是O(nlogn)。

快速排序:

快速排序的核心思想是,找到一个基准,使序列中小于该基准的元素都在该基准的左侧,大于该基准的元素都在该基准的右侧,然后以基准为边界,对基准左边
和基准右边进行同样的找基准然后小于该基准的元素都放在该基准的左侧····直到基准左右两侧只剩一个元素为止,此时序列有序,(升序)。算法复杂度:最好O(nlogn),最坏
O(n^2),平均O(nlogn)。快速排序通常要比其他排序算法要快。