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

来源:互联网 发布:vscode在插件 编辑:程序博客网 时间:2024/06/03 16:18
 

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>
07using namespace std;
08//此程序是实现计数排序算法,要特别注意指标问题
10void counting_sort(vector<int> A, vector<int>& B, int k);
11int 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  
24void 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=0i<n; ++i)
18            temp[i] = arr[i];
19  
20        for (int i=0i<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, 0sizeof(res));
38     int nbit = maxbit();
39     int tmp;
40     int radix = 1;
41     // 以下和计数排序一样
42     for(int i=1i<=nbit; ++i)
43     {
44         for(int j=0j<10++j)
45             hash[j] = 0;
46         for(int j=0j<n; ++j)
47         {
48             tmp = (arr[j]/radix)%10;
49             ++hash[tmp];
50         }
51         for(int j=1j<10++j)
52             hash[j] += hash[j-1];
53         for(int j=n-1j>=0--j)
54         {
55             tmp = (arr[j]/radix)%10;
56             --hash[tmp];
57             res[hash[tmp]] = arr[j];
58         }
59         for(int j=0j<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=0i<n; ++i)
72         cin >> arr[i];
73     radixSort();
74     cout << "排序后结果为: " << endl;
75     for(int i=0i<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>
09using namespace std;
10  
11vector<vector<double>> bucket_sort(vector<double> vec);
12  
13int 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//从大到小排序
34vector<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}
原创粉丝点击