计数排序是一个非基于比较的线性时间排序算法。它对输入的数据有附加的限制条件:
1、输入的线性表的元素属于有限偏序集S;
2、设输入的线性表的长度为n,|S|=k(表示集合S中元素的总数目为k),则k=O(n)。
在这两个条件下,计数排序的复杂性为O(n)。
计数排序算法的基本思想是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于x的值,则x可以直接存放在输出序列的第18个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,因此,上述方案还要作适当的修改。
假设输入的线性表L的长度为n,L=L1,L2,..,Ln;线性表的元素属于有限偏序集S,|S|=k且k=O(n),S={S1,S2,..Sk};则计数排序算法可以描述如下:
- 扫描整个集合S,对每一个Si∈S,找到在线性表L中小于等于Si的元素的个数T(Si);
- 扫描整个线性表L,对L中的每一个元素Li,将Li放在输出线性表的第T(Li)个位置上,并将T(Li)减1。
具体的实现如下:

















其中a为输入,b为输出,l为元素个数,k为元素最大值。
我们看到,计数排序算法没有用到元素间的比较,它利用元素的实际值来确定它们在输出数组中的位置。因此,计数排序算法不是一个基于比较的排序算法,从而它的计算时间下界不再是Ω(nlogn)。另一方面,计数排序算法之所以能取得线性计算时间的上界是因为对元素的取值范围作了一定限制,即k=O(n)。如果k=n2,n3,..,就得不到线性时间的上界。此外,我们还看到,由于算法第4行使用了downto语句,经计数排序,输出序列中值相同的元素之间的相对次序与他们在输入序列中的相对次序相同,换句话说,计数排序算法是一个稳定的排序算法。
用计数排序可以解决POJ的2371
题目:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2696 | Accepted: 1501 |
Description
Input
Output
Sample Input
5 7 121 123 7 121 ### 4 3 3 2 5
Sample Output
121 121 7 123
Source
#include <iostream>
using namespace std;
#define MAXN 100000
#define MAXM 5001
static int temp[MAXM];
int main(int argc,char **argv)
{
int i,j;
int T[MAXN];
int H[MAXN];
int n;
cin>>n;
for(i=0;i<n;i++)
cin>>T[i];
for(j = 0; j < n; j++) temp[T[j]]++;
for(j = 1; j < MAXM; j++) temp[j] += temp[j - 1];
for(j = n - 1; j >= 0; j--)
{
H[temp[T[j]] - 1] = T[j];
temp[T[j]]--;
}
int k;
cin>>k;
for(i=0;i<k;i++)
{
int j;
cin>>j;
cout<<H[j+1]<<endl;
}
return 0;
}