算法 计数排序CountSort

适用范围:数字重复出现比较多,分布区间小

1.遍历找到最大值最小值确定区间

    int nMax=arr[0];//最大值
    int nMin=arr[0];//最小值
    //遍历数组得到数组的最大值和最小值
    for (int i = 1; i < len; i++) {
        if (arr[i] > nMax) nMax = arr[i];
        if (arr[i] < nMin)nMin = arr[i];
    }

2.申请计数器数组初值为0

    //根据最大值最小值确定范围,申请数组
    int nSize = nMax - nMin + 1;
    int* parr = (int*)malloc(sizeof(int) * nSize);
    memset(parr, 0, sizeof(int) * nSize);//初始化为0 

3.对数字进行计数  

    for (int i = 0; i < len; i++) {
        parr[arr[i]-nMin]++;//统计各个数出现的次数
    } 

4.将计数数组按一定方法输出就是排序后的结果  

    //输出结果
    for (int i = 0; i < nSize; i++) {
        for (int j = 0; j < parr[i]; j++)
        {
            printf("%d ", i + nMin);
        }
    } 

 最终程序如下:

void CountSort(int* arr, int len) {
	int nMax=arr[0];//最大值
	int nMin=arr[0];//最小值
	//遍历数组得到数组的最大值和最小值
	for (int i = 1; i < len; i++) {
		if (arr[i] > nMax) nMax = arr[i];
		if (arr[i] < nMin)nMin = arr[i];
	}
	//根据最大值最小值确定范围,申请数组
	int nSize = nMax - nMin + 1;
	int* parr = (int*)malloc(sizeof(int) * nSize);
	memset(parr, 0, sizeof(int) * nSize);//初始化为0
	for (int i = 0; i < len; i++) {
		parr[arr[i]-nMin]++;//统计各个数出现的次数
	}
	//输出结果
	for (int i = 0; i < nSize; i++) {
		for (int j = 0; j < parr[i]; j++)
		{
			printf("%d ", i + nMin);
		}
	}
	printf("\n");
    free(parr);
	parr = NULL;
}

优化后:

1.遍历找到最大值最小值确定区间

    int nMax=arr[0];//最大值
    int nMin=arr[0];//最小值
    //遍历数组得到数组的最大值和最小值
    for (int i = 1; i < len; i++) {
        if (arr[i] > nMax) nMax = arr[i];
        if (arr[i] < nMin)nMin = arr[i];
    }

2.申请计数器数组初值为0  

    //根据最大值最小值确定范围,申请数组
    int nSize = nMax - nMin + 1;
    int* parr = (int*)malloc(sizeof(int) * nSize);
    memset(parr, 0, sizeof(int) * nSize);//初始化为0 

3.对数字进行计数  

    for (int i = 0; i < len; i++) {
        parr[arr[i]-nMin]++;//统计各个数出现的次数
    } 

4.获得各个分数最后出现的名次

    // 得到名次
    for (int i = 1; i < nSize; i++) {
        parr[i] += parr[i-1];
    } 

5.申请一个长度与原数组相同的数组用来保存排序结果  

    //创建一个新数组,长度与原数组相同
    int* pTemp = (int*)malloc(sizeof(int) * len);
    memset(pTemp, 0, sizeof(int) * len);//初始化为0 

6.进行排序

parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1

最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应最后出现的名次位置上

    //进行排序
    for (int i = len - 1; i >= 0; i--) {
        //parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1
        //最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应名次位置上
        pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];//将原数组元素放到其对应名次上
        parr[arr[i] - nMin]--;//因为已经在对应名次上插入了需要更新一下,对应元素最后出现的名次-1
    } 

7.把新数组的内容拷贝到原数组  

    for (int i = 0; i < len; i++) {
        arr[i] = pTemp[i];
    } 

最终程序如下:

void CountSort2(int* arr, int len) {
	int nMax = arr[0];//最大值
	int nMin = arr[0];//最小值
	//遍历数组得到数组的最大值和最小值
	for (int i = 1; i < len; i++) {
		if (arr[i] > nMax) nMax = arr[i];
		if (arr[i] < nMin)nMin = arr[i];
	}
	//根据最大值最小值确定范围,申请数组
	int nSize = nMax - nMin + 1;
	int* parr = (int*)malloc(sizeof(int) * nSize);
	memset(parr, 0, sizeof(int) * nSize);//初始化为0
	for (int i = 0; i < len; i++) {
		parr[arr[i] - nMin]++;//统计各个数出现的次数
	}
	// 得到各个分数最后出现的名次
	for (int i = 1; i < nSize; i++) {
		parr[i] += parr[i-1];
	}
	//创建一个新数组,长度与原数组相同
	int* pTemp = (int*)malloc(sizeof(int) * len);
	memset(pTemp, 0, sizeof(int) * len);//初始化为0
	//进行排序
	for (int i = len - 1; i >= 0; i--) {
        //parr[arr[i] - nMin]获得arr[i]分数的排名,因为数组是从0开始需要-1
        //最后pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];就是把原数组对应元素放在新数组的对应名次位置上
		pTemp[ parr[arr[i] - nMin] - 1 ] = arr[i];//将原数组元素放到其对应名次上
		parr[arr[i] - nMin]--;//因为已经在对应名次上插入了需要更新一下,对应元素最后出现的名次-1
	}
	//把新数组的内容拷贝到原数组
	for (int i = 0; i < len; i++) {
		arr[i] = pTemp[i];
	}
	free(pTemp);
	pTemp = NULL;
	free(parr);
	parr = NULL;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值