算法 计数排序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;
}

 

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 计数排序是一种非比较排序算法。它的基本思想是对于给定的输入序列中的每一个元素,确定该元素在输入序列中的出现次数。然后根据出现次数对所有元素进行排序。 下面是一个示例JS代码: ``` function countSort(arr) { var max = Math.max.apply(null, arr); var min = Math.min.apply(null, arr); var count = new Array(max - min + 1).fill(0); for (var i = 0; i < arr.length; i++) { count[arr[i] - min]++; } var index = 0; for (var i = min; i <= max; i++) { while (count[i - min]-- > 0) { arr[index++] = i; } } return arr; } ``` 请注意,此代码只能用于整数数组,并且需要额外的空间来存储计数数组。 ### 回答2: 计数排序Counting Sort)是一种线性时间复杂度的排序算法,适用于待排序的数值范围较小的情况。该算法通过统计每个元素出现的次数,然后依次输出,实现排序的目的。 下面是一个使用JavaScript实现计数排序算法的例子: ```javascript function countingSort(arr) { let len = arr.length; if (len <= 1) { return arr; } // 找出待排序数组的最大值 let max = arr[0]; for (let i = 1; i < len; i++) { if (arr[i] > max) { max = arr[i]; } } // 创建一个计数数组,其中索引表示待排序元素值,值表示元素出现次数 let countArr = new Array(max + 1).fill(0); // 统计每个元素出现的次数 for (let i = 0; i < len; i++) { countArr[arr[i]]++; } // 对计数数组进行累加 for (let i = 1; i <= max; i++) { countArr[i] += countArr[i - 1]; } // 创建一个临时数组,存储排序后的结果 let tempArr = new Array(len); for (let i = len - 1; i >= 0; i--) { let value = arr[i]; let index = countArr[value] - 1; tempArr[index] = value; countArr[value]--; } // 将临时数组复制到原数组中 for (let i = 0; i < len; i++) { arr[i] = tempArr[i]; } return arr; } // 测试例子 let arr = [5, 8, 2, 1, 9, 5, 3, 3]; let sortedArr = countingSort(arr); console.log(sortedArr); // [1, 2, 3, 3, 5, 5, 8, 9] ``` 以上是一个简单的计数排序算法的JavaScript实现。希望对你有帮助! ### 回答3: 计数排序是一种非比较性的排序算法,它通过统计数组中每个元素出现的次数,进而确定每个元素的位置,从而实现排序。 以下是一个使用 JavaScript 实现的计数排序算法: ```javascript function countingSort(arr) { // 找出数组中的最大值和最小值,确定计数数组的大小 let max = Math.max(...arr); let min = Math.min(...arr); // 初始化计数数组 let counts = new Array(max - min + 1).fill(0); // 统计元素出现的次数 for (let i = 0; i < arr.length; i++) { counts[arr[i] - min]++; } // 根据计数数组重新排列原数组 let sortedArr = []; for (let i = 0; i < counts.length; i++) { while (counts[i] > 0) { sortedArr.push(i + min); counts[i]--; } } return sortedArr; } // 测试 let arr = [8, 2, 4, 9, 3, 6, 5, 1, 7]; let sortedArr = countingSort(arr); console.log(sortedArr); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9] ``` 以上代码实现了计数排序算法。首先,找出数组中的最大值和最小值,确定计数数组的大小。然后,初始化计数数组,统计每个元素出现的次数。接下来,根据计数数组重新排列原数组,并返回排序后的数组。 计数排序的时间复杂度为 O(n + k),其中 n 是待排序数组的长度,k 是待排序数组中的最大值和最小值的差。计数排序是一种稳定排序算法,适用于对一定范围内的整数进行排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值