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个数字右对齐排成一列。然后把相同的位数互相比较,来排序
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
桶排序算法想法类似于散列表
首先要假设待排序的元素输入符合某种均匀分布,例如数据均匀分布在[ 0,1)区间上.
则可将此区间划分为10个小区间,称为桶,每个桶存放一个链表,对散布到同一个桶
中的元素在排序。
01 | // bucketsort.cpp : 定义控制台应用程序的入口点。 |
02 | // 桶排序算法,要用到前面的堆排序算法进行桶内的排序 |
03 | //肖成 2011/3/28 |
04 | #include "vectorheap.h" |
05 | #include <iostream> |
06 | #include <list> |
07 | #include <algorithm> |
08 | #include <cstdlib> |
09 | using namespace std; |
10 | |
11 | vector<vector< double >> bucket_sort(vector< double > vec); |
12 | |
13 | int main() |
14 | { |
15 | double a[]={0.34,0.21,0.41,0.11,0.32,0.42,0.22,0.51,0.62,0.71}; |
16 | |
17 | vector< double > vec(a,a+10); |
18 | vector<vector< double >> lstvec; |
19 | |
20 | lstvec=bucket_sort(vec); |
21 | vector< double >::iterator vecIter; |
22 | vector<vector< double >>::iterator lstIter; |
23 | |
24 | for (lstIter=lstvec.begin(); lstIter!=lstvec.end();lstIter++) |
25 | { |
26 | for (vecIter=(*lstIter).begin();vecIter!=(*lstIter).end();vecIter++) |
27 | cout<<*vecIter<< " ; |
28 | } |
29 | cout<<endl; |
30 | return 0; |
31 | } |
32 | |
33 | //从大到小排序 |
34 | vector<vector< double >> bucket_sort(vector< double > vec) |
35 | { |
36 | int n=vec.size(); |
37 | vector<vector< double >> lst(n); |
38 | vector<vector< double >>::iterator iter; |
39 | |
40 | //计算散布到桶的位置,因为是从大到小所以要倒序散布 |
41 | for ( int i=0;i<n;i++) |
42 | lst.at(( int )(n-n*vec.at(i))).push_back(vec.at(i)); |
43 | |
44 | for ( int i=n-1; i>=0; i--) |
45 | { |
46 | //对桶内的元素进行堆排序 |
47 | vectorheap< double > vecheap(lst.at(i)); |
48 | lst.at(i)=vecheap.sortHeap(); |
49 | } |
50 | return lst; |
51 | } |