基本排序算法
------ 关键词 ------
内排序:在排序过程中,所有元素调到内存中进行的排序。内排序效率用比较次数来衡量。
外排序:在数据量大的情况下,只能分块排序。外排序还需要用读/写外存的次数来衡量其效率。
排序算法的稳定性:
排序算法稳定性的简单形式化定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。通俗地讲就是保证排序前后两个相等的数的相对顺序不变。
对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。
空间复杂度:
时间复杂度:
时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。(一般指的算法中的基本操作一般指算法中最深层循环内的语句)
常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
---------------------排序算法--->
*冒泡排序(BubbleSort):两个数比较大小,较大的数下沉,较小的数冒起来;
*选择排序(SelctionSort):在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;... ...第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成;
*插入排序(Insertion Sort):在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序;
*希尔排序(Shell Sort):在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序;
*快速排序(Quicksort):(分治)先从数列中取出一个数作为key值;将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;对左右两个小数列重复第二步,直至各区间只有1个数;
*归并排序(Merge Sort)归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。首先考虑下如何将2个有序数列合并。这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可;
*基数排序(RadixSort):首先创建数组A[MaxValue];然后将每个数放到相应的位置上(如 17放在下标17的数组位置);最后遍历数组,即为排序后的结果;
*堆排序(HeapSort):http://blog.****.net/xiaoxiaoxuewen/article/details/7570621/
http://blog.****.net/yxb_yingu/article/details/51336197
*二叉树排序: http://blog.****.net/chenxieyy/article/details/48181203
*计数排序 (CountSort):对每一个输入元素x,确定出小于x的元素个数,有了这一信息,就可以把x直接放在它在最终输出数组的位置上,例如,如果有17个元素小于x,则x就是属于第18个输出位置。当几个元素相同是,方案要略作修改。http://blog.****.net/tanyujing/article/details/8534843
*桶排序(BucketSort): http://www.cnblogs.com/kkun/archive/2011/11/23/2260267.html(很耗内存空间)
-------*******-------*******--------*******-------
外部排序的理解:
外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。广义上讲,可以将其看作一个归并的排序过程。
举个例子:TOP K问题
有记录数据100G,从中选出从大TOP50的数据,但是本身计算机内存仅有2G。在此预设下就需要用到外部排序了。
-----------
每次把2G的数据从文件中传入内存,然后用一个"合适的排序算法"在内存中排好序后,再将这有序数据载入一个2G大小的文件
-----------
再载入第二个2G数据... ...循环50遍之后,现在得到50个文件,每个文件2G,文件内部是有序的
-----------
不断将这50个2G 数据进行一个归并,最终就能得到这100G的有序数据文件
----------- 优化处理 ---------
@增设一个缓冲buffer,加速从文件到内存的转储;
@把文件中的2G数据载入内存这个过程定义为”L”,把内存中的排序过程定义为”S” ,把排序好的 2G数据再转储到另一个文
这个过程定义为”T”,而后采用流水线并行实现,但需要注意防止死锁,另外,将内存平均分为三份,分别用于处理三个阶段
的数据。这样带来的影响是,现在一次就不能处理2G数据了,只能处理2/3G的数据,流水线会加长;
@归并就是不断在一组有序数列中找最小值,但是扫描每个文件头,找最大值,最差情形要比较50次,平均复杂度是O(n),n为
最后得到的有序数组的个数,优化措施:维护一个大小为n的“最大堆”,每次返回堆顶元素,就为当前所有文件头数值的那个
最大值。然后根据刚才弹出的那个最大值是属于哪个文件的,然后再将那个文件此时的头文件所指向的数,插入到最大堆中,文
件指针自动后移。插入过程为logn复杂度,但是每次返回最小值的复杂度为O(1),运行时空间复杂度为O(n)。
-----------
参考:
http://www.runoob.com/w3cnote/sort-algorithm-summary.html
http://www.cnblogs.com/eniac12/p/5329396.html
http://www.jianshu.com/p/f5baf7f27a7e
http://blog.****.net/wangqyoho/article/details/52584640
http://blog.****.net/jeason29/article/details/50474772