1.决策树模型
比较排序的过程可以被抽象地视为决策树。一棵决策树是一棵满二叉树,表示某排序算法作用于给定输入所做的所有比较。排序算法的执行对应于遍历一条从树的根到叶节点的路径。每个内结点对应一个比较ai&aj,左子树决定着ai<=aj以后的比较,右子树决定着ai>aj以后的比较。当到达一个叶节点时,排序算法就已确定。排序算法能够正确工作的的必要条件是,n个元素的n!种排列都要作为决策树的一个叶节点出现。设决策树的高度为h,叶子数目为l,那么有 2h>=l>=n!,于是有 h>lgn!
= Ω(nlgn)。 这说明比较排序的最坏时间复杂度为Ω(nlgn)。这也说明合并排序和堆排序的复杂度已经渐进最优了。
2.计数排序
假设n个输入元素的每一个都是介于0到k之间的整数,此处k为某个整数。当k=O(n)时,计数排序的运行时间为Θ(n)。
假定输入是数组A[1...n], 存放排序结果的B[1...n],以及提供计数临时存储的C[0...k]。
COUNTING-SORT(A,B,k)jk
1
2
3
4
//到此时C[i]中数值表示A中等于i的元素个数
5
6
//到此时C[i]中数值表示A中等于小鱼等于i的元素个数
7
8
9
第七行,从length[A] downto 1是为了正确解决由相同元素时的排序情况,保证算法稳定。若改为for
i<-
05 |
#include <vector> |
06 |
#include <iostream> |
07 |
using namespace std; |
08 |
//此程序是实现计数排序算法,要特别注意指标问题 |
10 |
void counting_sort(vector< int > A, vector< int >& B, int k); |
11 |
int main() |
12 |
{ |
13 |
int a[]={1,4,3,2,0,4,3,5,7,5,4,6,7,8,5,9,6,4,3,4,0}; |
14 |
int k=9; |
15 |
vector< int > A(a,a+20); |
16 |
vector< int > B(20,0); |
17 |
counting_sort(A, B, k); |
18 |
vector< int >::iterator i; |
19 |
for (i=B.begin();i!=B.end();i++) |
20 |
cout<<*i<< " ; |
21 |
return 0; |
22 |
} |
23 |
|
24 |
void counting_sort(vector< int > A, vector< int >& B, int k) |
25 |
{ |
26 |
vector< int > C(k+1,0); |
27 |
//统计A中重复元素的个数,C的指标表示这个元素的值,C的值表示对应元素的个数 |
28 |
for ( int j=0;j<A.size();j++) |
29 |
C[A[j]]=C[A[j]]+1; |
30 |
//统计这个值在数组中的放置的位置,即排在第几位 |
31 |
for ( int i=1;i<=k;i++) |
32 |
C[i]=C[i]+C[i-1]; |
33 |
//一次将A中的每个元素放到正确的位置,计入数组下标应从0开始,因此用C[A[j]]减去1 |
34 |
for ( int j=A.size()-1;j>=0;j--) |
35 |
{ |
36 |
B[C[A[j]]-1]=A[j]; |
37 |
C[A[j]]=C[A[j]]-1; |
38 |
} |
39 |
} |
3.基数排序
基本思想:按组成关键字的各个位的值来实现排序的
基数:计算的基数就是基本的单元数。比如10进制的基数就是10,二进制的基数就2,八进制的基数是8等等。
基数排序说通俗点,就是把带排序的N个数字右对齐排成一列。然后把相同的位数互相比较,来排序
11
15
16
17
18
21
23
24
26
27
34
37
38
41
42
43
45
46
47
49
50