/*
计数排序:n个元素都是0到k范围得整数,当k=O(n)时,排序运行时间为O(n)
思想:对于数x,确定小于x的个数m,将x放在第m+1个位置上
例子:假设3个元素小于x,那么x应该放在4上
输入第一行的第一个数n是数组的个数,第一行第二个数表示所有n的元素中最大的数k
接下来的第二行就是n个数字
输入:
8 5
2 5 3 0 2 3 0 3
输出:
0 0 2 2 3 3 3 5
*/
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
void countSort(int* pArr, int n, int k)
{
//先初始化一个含有k个元素的数组C用于统计,这里k下标需要用到,所以实例化长度为k+1
int* cArr = new int[k+1];
//注意对于指针数组初始化,不能用memset,只能从头到尾赋值为0
//memset(cArr , 0 , k+1);
for(int i = 0 ; i <= k ; i++)
{
cArr[i] = 0;
}
//计数
for(int i = 0 ; i < n ; i++)
{
cArr[ pArr[i] ] += 1;
}
//生成每个元素x小于等于x的个数,这里才用从前向后累加的方式,例如c[1]=c[1]+c[0]=1+1,<=1的元素个数为2,
//c[2]=c[2]+c[1]=1+2=3,注意k必须取到
for(int i = 1 ; i <= k ; i++)
{
cArr[i] = cArr[i] + cArr[i-1];
}
//对计数数组进行排序,输入到中间数组B中,该数组的长度为n,在该数组中采用从后向前输出
int* bArr = new int[n];
for(int i = n - 1 ; i >= 0 ; i--)
{
//B数组的下标应该就是个数,下标最大的是cArr[k]计数最大,但是cArr[k]对应的数字是?,],这里不需要从B数组最大开始摆放,
//只需要按照原来数组从后向前摆放,pArr[n-1]对应的是原数组最后一个数字,这个数字最终所在位置是cArr[ pArr[n-1] ]
//而cArr[ pArr[n-1] ] - 1,则使得数字pArr[n-1]对应的摆放下标减一,在b数组的摆放位置cArr[ pArr[i] ]中摆放数字pArr[i]
int a = pArr[i];
int b = cArr[a];
//因为这里下标从0开始,因此数字pArr[i]对应的摆放位置cArr[ pArr[i] ]实际需要减1
bArr[ cArr[ pArr[i] ] - 1 ] = pArr[i];
//使得数字pArr[i]对应的下标减一,防止出现数组中有相同数字的情况,摆放位置减1
cArr[ pArr[i] ] -= 1;
}
//此时B数组中就是结果
for(int i = 0 ; i < n ; i++)
{
pArr[i] = bArr[i];
}
delete[] bArr;
delete[] cArr;
}
void print(int* pArr,int n)
{
for(int i = 0 ; i < n ; i++)
{
cout << pArr[i] << " ";
}
}
void process()
{
int n , k;
while(cin >> n >> k)
{
int* pArr = new int[n];
for(int i = 0 ; i < n ; i++)
{
cin >> pArr[i];
}
countSort(pArr , n , k);
print(pArr , n);
delete[] pArr;
}
}
int main(int argc,char* argv[])
{
process();
system("pause");
return 0;
}
算法导论:第8章 线性时间排序__计数排序
最新推荐文章于 2024-06-23 11:06:04 发布