C ++ 计数排序

// 计数排序
void CountSort(int arr[], int length)
{	// 序列的最大值决定了数组的长度
	int max = arr[0];
	for (int i = 0; i < length; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}

	int* countArr = new int[max + 1];
	 // 将新申请的动态数组内容全部置为初值0
	for (int i = 0; i <= max; i++)
	{
		countArr[i] = 0;
	}
	// 遍历数组,统计相同的数字出现的个数
	for (int i = 0; i < length; i++)
	{
		countArr[arr[i]]++;

	}
	int index = 0;
	for (int i = 0; i < max+1; i++)
	{
		for (int j = 0; j < countArr[i]; j++)  // 当统计个数为0时,不赋值。
		{
			arr[index++] = i;	// 再赋值回原数组
		}
	}

}

//如果遇到类似85,78,56,97,96,98,90这样的序列,前面的方法显然浪费了很多的空间。因此不再以原始序列中的最大值max+1作为数组最大长度,而是以原始序列中的最大值max与最小值min之差+1,即max-min+1作为数组最大长度。

// 计数排序(优化版)
int* CountSort(int arr[], int length)
{	// 找出数组中的最大值和最小值
	int max = arr[0];
	int min = arr[0];
	for (int i = 0; i < length; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}
	int d = max - min;
	int* countArr = new int[d + 1];
	 // 将新申请的动态数组内容全部置为初值0
	for (int i = 0; i <= d; i++)
	{
		countArr[i] = 0;
	}
	// 遍历数组,统计相同的数字出现的个数
	for (int i = 0; i < length; i++)
	{
		countArr[arr[i] - min]++;

	}
	 // 对统计数组做处理,后面的元素等于前面所有元素之和,找到重复元素的最靠后位置,然后和它相同的元素在它前面,解决了统计数组中相同元素谁在前谁在后的问题,保持了原序列的稳定性排序。这里是在统计数组中之间表示出原序列的绝对位置
	int sum = 0;
	for (int i = 0; i <= d; i++)
	{
		sum = sum + countArr[i];
		countArr[i] = sum;
	}

	int* SortArr = new int[d + 1];
	int index = 0;
	for (int i = length-1; i >= 0; i--)
	{
		SortArr[countArr[arr[i]-min] - 1] = arr[i];
		countArr[arr[i] - min]--;
	}
	return SortArr;
}


int main()
{
	//int array[] = { 5,3,1,6,9,8,4 };
	int array[] = { 8,2,2,7,5,7 };
	for (int i = 0; i < sizeof(array)/sizeof(int); i++)
	{
		cout << array[i] << (i != sizeof(array) / sizeof(int) ? " ": "\n");
	}
	cout << "\n";
	
	int* p = CountSort(array, sizeof(array) / sizeof(int));

	int i = 0;
	while (i < sizeof(array)/sizeof(int))
	{
		cout << p[i] << (i == (sizeof(array) / sizeof(int)) ? "\n": " ");
		i++;
	}	

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值