基本排序算法

------ 关键词 ------

内排序在排序过程中,所有元素调到内存中进行的排序。内排序效率用比较次数来衡量。

外排序:在数据量大的情况下,只能分块排序。外排序还需要用读/写外存的次数来衡量其效率。

排序算法的稳定性:

  排序算法稳定性的简单形式化定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。通俗地讲就是保证排序前后两个相等的数的相对顺序不变。

  对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法

空间复杂度:

一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。  
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常          量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
       一个算法所需的存储空间用f(n)表示。S(n)=O(f(n))  其中n为问题的规模,S(n)表示空间复杂度。

时间复杂度:

时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。(一般指的算法中的基本操作一般指算法中最深层循环内的语句)

(2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。算法中基本操作重复执行的频度T(n)是问题规模n的某个函数,f(n),记做T(n)=O(f(n));
  时间频度不同,但时间复杂度可能相同。如:T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。
注:
      最坏时间复杂度和平均时间复杂度  最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说明,讨论的时间复杂度均是最坏情况下的时间复杂度。 这样做的原因是:最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界,这就保证了算法的运行时间不会比任何更长。
      平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。

     常见的算法时间复杂度由小到大依次为:Ο(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.csdn.net/xiaoxiaoxuewen/article/details/7570621/         http://blog.csdn.net/yxb_yingu/article/details/51336197

*二叉树排序: http://blog.csdn.net/chenxieyy/article/details/48181203

*计数排序 (CountSort):对每一个输入元素x,确定出小于x的元素个数,有了这一信息,就可以把x直接放在它在最终输出数组的位置上,例如,如果有17个元素小于x,则x就是属于第18个输出位置。当几个元素相同是,方案要略作修改。http://blog.csdn.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.csdn.net/wangqyoho/article/details/52584640

http://blog.csdn.net/jeason29/article/details/50474772







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值