<script src="http://blog.csdn.net/count.aspx?ID=1476227&Type=Rank" type="text/javascript"></script>
计数排序是一个非基于比较的线性时间排序算法。它对输入的数据有附加的限制条件:
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。
具体的实现如下:
void
Counting_Sort(
int
a[],
int
b[],
int
l,
int
k)
...
{ int* c = new int[k]; memset(c, 0, k * sizeof(int)); for (int j = 0; j < l; j++) c[a[j]]++; for (int j = 1; j < k; j++) c[j] += c[j - 1]; for (int j = l - 1; j >= 0; j--) ...{ b[c[a[j]] - 1] = a[j]; c[a[j]]--; } delete []c; }
其中a为输入,b为输出,l为元素个数,k为元素最大值。
我们看到,计数排序算法没有用到元素间的比较,它利用元素的实际值来确定它们在输出数组中的位置。因此,计数排序算法不是一个基于比较的排序算法,从而它的计算时间下界不再是Ω(nlogn)。另一方面,计数排序算法之所以能取得线性计算时间的上界是因为对元素的取值范围作了一定限制,即k=O(n)。如果k=n2,n3,..,就得不到线性时间的上界。此外,我们还看到,由于算法第4行使用了downto语句,经计数排序,输出序列中值相同的元素之间的相对次序与他们在输入序列中的相对次序相同,换句话说,计数排序算法是一个稳定的排序算法。
用计数排序可以解决POJ的2371
题目:
Questions and answers
Time Limit: 1000MS | | Memory Limit: 65536K |
Total Submissions: 2696 | | Accepted: 1501 |
Description
The database of the Pentagon contains a top-secret information. We don't know what the information is — you know, it's top-secret, — but we know the format of its representation. It is extremely simple. We don't know why, but all the data is coded by the natural numbers from 1 up to 5000. The size of the main base (we'll denote it be N) is rather big — it may contain up to 100 000 those numbers. The database is to process quickly every query. The most often query is: "Which element is i-th by its value?"— with i being a natural number in a range from 1 to N. Your program is to play a role of a controller of the database. In the other words, it should be able to process quickly queries like this.
Input
The standard input of the problem consists of two parts. At first, a database is written, and then there's a sequence of queries. The format of database is very simple: in the first line there's a number N, in the next N lines there are numbers of the database one in each line in an arbitrary order. A sequence of queries is written simply as well: in the first line of the sequence a number of queries K (1 <= K <= 100) is written, and in the next K lines there are queries one in each line. The query "Which element is i-th by its value?" is coded by the number i. A database is separated from a sequence of queries by the string of three symbols "#".
Output
The output should consist of K lines. In each line there should be an answer to the corresponding query. The answer to the query "i" is an element from the database, which is i-th by its value (in the order from the least up to the greatest element).
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;
}