算法导论:第8章 线性时间排序__计数排序

来源:互联网 发布:收发存excel怎么编程 编辑:程序博客网 时间:2024/05/21 22:33
/*计数排序:n个元素都是0到k范围得整数,当k=O(n)时,排序运行时间为O(n)思想:对于数x,确定小于x的个数m,将x放在第m+1个位置上例子:假设3个元素小于x,那么x应该放在4上输入第一行的第一个数n是数组的个数,第一行第二个数表示所有n的元素中最大的数k接下来的第二行就是n个数字输入:8 52 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+1int* 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] ]实际需要减1bArr[ cArr[ pArr[i] ] - 1 ] = pArr[i];//使得数字pArr[i]对应的下标减一,防止出现数组中有相同数字的情况,摆放位置减1cArr[ 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;}

0 0
原创粉丝点击