算法导论——第五章——线性时间排序

 

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)。 计数排序的思想就是对每一个输入元素x,确定出小于x的元素个数。有了这一信息,就可以把x直接放到最终输出数组的位置上。

假定输入是数组A[1...n], 存放排序结果的B[1...n],以及提供计数临时存储的C[0...k]。

COUNTING-SORT(A,B,k)jk

   for  i<- 0 to k

       do C[i] i<- 0 //初始化临时存储数组

   for j i<-1 to length[A]

       do C[A[j]] =C[A[j]]+1

//到此时C[i]中数值表示A中等于i的元素个数

   for i <-1 to k

       do C[i] = C[i] + C[i-1]

//到此时C[i]中数值表示A中等于小鱼等于i的元素个数

   for i <- length[A] downto 1

       do B[C[A[i]] = A[i]

            C[A[i]] = C[A[i]] -1  //important

第七行,从length[A] downto 1是为了正确解决由相同元素时的排序情况,保证算法稳定。若改为for i<- 1 upto length[A],则排序不稳定。


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个数字右对齐排成一列。然后把相同的位数互相比较,来排序

 6  #include  < iostream >
 7  #include  < cstring >
 8  using   namespace  std;
 9   
10  int  arr[ 100 ], res[ 100 ], hash[ 10 ];
11  int  n;
12   
13  int  maxbit()
14  {
15          int  _max  =   0 ;
16          int  temp[ 100 ];
17          for ( int  i = 0 i < n;  ++ i)
18             temp[i]  =  arr[i];
19   
20          for  ( int  i = 0 i < n;  ++ i)
21         {
22                 int  tt  =   1 ;
23                 while (temp[i] / 10   >   0 )
24                {
25                       tt ++ ;
26                       temp[i]  /=   10 ;
27                }
28                 if (_max  <  tt)
29                       _max  =  tt;
30         }
31         cout  <<   " _max  "   <<  _max  <<  endl;
32          return  _max;
33  }
34   
35  void  radixSort()
36  {
37      memset(res,  0 sizeof (res));
38       int  nbit  =  maxbit();
39       int  tmp;
40       int  radix  =   1 ;
41       //  以下和计数排序一样
42       for ( int  i = 1 i <= nbit;  ++ i)
43      {
44           for ( int  j = 0 j < 10 ++ j)
45              hash[j]  =   0 ;
46           for ( int  j = 0 j < n;  ++ j)
47          {
48              tmp  =  (arr[j] / radix) % 10 ;
49               ++ hash[tmp];
50          }
51           for ( int  j = 1 j < 10 ++ j)
52              hash[j]  +=  hash[j - 1 ];
53           for ( int  j = n - 1 j >= 0 -- j)
54          {
55              tmp  =  (arr[j] / radix) % 10 ;
56               -- hash[tmp];
57              res[hash[tmp]]  =  arr[j];
58          }
59           for ( int  j = 0 j < n;  ++ j)
60              arr[j]  =  res[j];
61          radix  *=   10 ;
62      }
63  }
64   
65  int  main()
66  {
67      freopen( " input.txt " " r " stdin);
68      cout  <<   " 输入元素个数:  " ;
69      cin  >>  n;
70      cout  <<   " 输入 "   <<   <<   " 个元素:  "   <<  endl;
71       for ( int  i = 0 i < n;  ++ i)
72          cin  >>  arr[i];
73      radixSort();
74      cout  <<   " 排序后结果为:  "   <<  endl;
75       for ( int  i = 0 i < n;  ++ i)
76          cout  <<  res[i]  <<   "   " ;
77      cout  <<  endl;
78  }
4.桶排序(期望时间复杂度O(n))

桶排序算法想法类似于散列表

首先要假设待排序的元素输入符合某种均匀分布,例如数据均匀分布在[ 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 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值