返回目录 
在排序过程中,若整个表都是放在内存中处理,排序时不涉及数据的内、外存交换,则称之为 内排序  。根据内排序算法是否 基于关键字的比较  ,将内排序算法分为 基于比较的排序算法  和不基于比较的排序算法。
基数排序是典型的不基于比较的排序算法。 基于比较的排序算法中,主要进行 比较  、 移动  这两种基本操作,这类排序算法的性能由算法的 时间和空间  确定的,而时间是由比较和移动的次数之和确定的,例如,两个记录的一次交换一般需要三次移动。 若排序过程中要进行 数据的内、外存交换  ,则称之为 外排序 。
如果待排序的表中,存在有多个关键字相同的记录,经过排序后这些具有 相同关键字  的记录之间的 相对次序保持不变  ,称这种排序方法是 稳定  的。 希尔、快排、选择排序是不稳定的 (重要)。
每一趟将一个待排序的元素,按大小 插入到已经排序中  的适当位置上。
时间Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) \Omega(n)-\Theta(n^{2})-\mathrm{O}(n^{2}) Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 稳定 。
优化了个寂寞,其瓶颈主要是顺序表的移动。
时间Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) \Omega(n)-\Theta(n^{2})-\mathrm{O}(n^{2}) Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 稳定 。
基于插入排序,将待排序数组 分割成多个子序列  ,这些子序列的元素间隔一定步长,然后 对每个子序列进行插入排序  ,随着 步长的逐渐减小 ,最终整个数组变为有序。
时间Ω ( n log  n ) − Θ ( n 1.3 ) − O ( n 2 ) \Omega(n\log n)-\Theta(n^{1.3})-\mathrm{O}(n^{2}) Ω ( n log  n ) − Θ ( n 1 . 3 ) − O ( n 2 ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 不稳定 。
倒序遍历,如果相邻两项不是有序的,就交换之,重复多轮。
时间Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) \Omega(n)-\Theta(n^{2})-\mathrm{O}(n^{2}) Ω ( n ) − Θ ( n 2 ) − O ( n 2 ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 稳定 。
选择一个基准元素,通过一趟排序将待排序的数组分割成独立的两部分,其中一部分的所有元素都不大于另一部分的所有元素,然后递归地对这两部分继续进行快速排序,直至整个数组有序。快速排序在被排序的数组随机分布下最容易发挥其长处。
时间Ω ( n log  n ) − Θ ( n log  n ) − O ( n 2 ) \Omega(n\log n)-\Theta(n\log n)-\mathrm{O}(n^{2}) Ω ( n log  n ) − Θ ( n log  n ) − O ( n 2 ) Ω ( log  n ) − Θ ( log  n ) − O ( log  n ) \Omega(\log n)-\Theta(\log n)-\mathrm{O}(\log n) Ω ( log  n ) − Θ ( log  n ) − O ( log  n ) 不稳定 。
提醒:未经任何优化的快排,最坏时间是O ( n 2 ) \mathrm{O}(n^{2}) O ( n 2 ) std 中的快排是优化过的,保证上界严格不超过O ( n log  n ) \mathrm{O}(n\log n) O ( n log  n ) 
每步从待排序的记录中选出关键字最小的记录,按顺序放在已排序的记录序列的最后,直到全部排完为止。
时间Ω ( n 2 ) − Θ ( n 2 ) − O ( n 2 ) \Omega(n^{2})-\Theta(n^{2})-\mathrm{O}(n^{2}) Ω ( n 2 ) − Θ ( n 2 ) − O ( n 2 ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 不稳定 。
大概思路掌握就行,具体细节不重要,其实作者也没看懂  
基于比较,利用堆这种数据结构的特性,首先将待排序数组构建成一个 大根堆  ,使得每个父节点的值都大于或等于其子节点的值;然后通过反复 移除堆顶元素  (最大值),将其与数组末尾元素交换,并重新 调整  堆以保持大根堆的性质,直到堆中只剩下一个元素,此时整个数组已经按照升序排列完成。
时间Ω ( n log  n ) − Θ ( n log  n ) − O ( n log  n ) \Omega(n\log n)-\Theta(n\log n)-\mathrm{O}(n\log n) Ω ( n log  n ) − Θ ( n log  n ) − O ( n log  n ) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) \Omega(1)-\Theta(1)-\mathrm{O}(1) Ω ( 1 ) − Θ ( 1 ) − O ( 1 ) 不稳定 。
多次将两个或两个以上的有序表合并成一个新的有序表,最简单的归并是直接将两个有序的子表合并成一个有序的表——二路归并排序 。
时间Ω ( n log  n ) − Θ ( n log  n ) − O ( n log  n ) \Omega(n\log n)-\Theta(n\log n)-\mathrm{O}(n\log n) Ω ( n log  n ) − Θ ( n log  n ) − O ( n log  n ) Ω ( n ) − Θ ( n ) − O ( n ) \Omega(n)-\Theta(n)-\mathrm{O}(n) Ω ( n ) − Θ ( n ) − O ( n ) 稳定 。
个人认为是最优雅的排序算法。放个代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ll merge_sort (vector<int >& a)   {	auto  solve = [&](this  auto && self, int  L, int  R) -> ll { 		if  (R - L <= 1 ) return  0ll ; 		int  m = L + R >> 1 ; 		ll res = self (L, m) + self (m, R); 		vector<int > b; 		int  l = L, r = m; 		while  (l < m && r < R) { 			if  (a[l] <= a[r]) b.push_back (a[l++]); 			else  b.push_back (a[r++]), res += m - l; 		} 		while  (l < m) b.push_back (a[l++]); 		while  (r < R) b.push_back (a[r++]); 		copy (b.begin (), b.end (), a.begin () + L); 		return  res; 	}; 	return  solve (0 , a.size ()); } 
通过 分配  和 收集  过程来实现排序, 而非比较 。根据数字的位数(如个位、十位、百位等)将数组分成不同的桶,然后在每一轮中,根据当前轮次的位数对所有桶中的元素进行收集和分配,使得相同位数的数字被放在一起,通过这种方式,从最低位到最高位逐轮进行,直到整个数组按照升序或降序排列完成。
时间O ( d ( n + r ) ) \mathrm{O}(d(n+r)) O ( d ( n + r ) ) O ( n ) \mathrm{O}(n) O ( n ) O ( r ) \mathrm{O}(r) O ( r ) r r r d d d Ω ( r ) − Θ ( r ) − O ( r ) \Omega(r)-\Theta(r)-\mathrm{O}(r) Ω ( r ) − Θ ( r ) − O ( r ) 稳定 。
对于整数,这是少有的线性排序方法。