排序算法(五)-- 线性时间排序之计数排序

计数排序

计数排序假设n个输入元素中的每一个都是介于0到k之间的整数,此处k为某个整数。当k = O(n)时,计数排序的运行时间为O(n).

计数排序的基本思想是:对于每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到输出数组中的位置上了。例如,如果有17个元素小于x则x就应该放在第18个位置上。当有几个元素相同时,这个方案要改,因为不能把他们放在同一个输出位置上。

在计数排序算法的代码中,假设输入是一个数组A[1 .. n]. 还需要数组B[1.. n]存放排序的输出,C[0 .. k]提供临时存储空间。

算法如下:


这里注意C数组,第一个for循环中为C申请k个空间并且置零,第二的for循环中,C记录了A数组中每个元素出现的个数,第三个for循环中,利用C,记录了A中每个元素最后一次出现的位置。第四个for循环中当元素依次取出是,C中表示A中相应元素位置的C[i]中的元素个数依次减1. 直到B中的元素放满。

程序代码:
/*
线性时间排序 -- 计数排序算法
*/

#include<iostream>
#include<stdlib.h>

using namespace std;

//函数声明
void CountingSort(int A[], int B[], int k);

void main()
{
	int A[21];
	int B[21];
	//待排序数组
	cout<<"待排序数组"<<endl;
	for(int i = 1; i <= 20; i++)
	{
		A[i] = rand()%10;
		cout<<A[i]<<" ";
	}
	cout<<endl;

	// 排序
	CountingSort(A,B,10);

	// 输出排序结果
	cout<<"排序结果"<<endl;
	for(int j = 1; j <= 20; j++)
	{
		cout<<B[j]<<" ";
	}
	cout<<endl;
}

//计数排序
void CountingSort(int A[], int B[], int k)
{
	int* C = new int[k];
	//初始化C
	for(int i = 0; i < k; i++)
	{
		C[i] = 0;
	}
	cout<<endl;
	//遍历A中的每个元素,如果一个输入元素的值为i,就将C[i]值加1;
	//遍历结束后,C[i]中保存的就是等于i的元素个数
	for(int j = 1; j <= 20; j++)
	{
		C[A[j]] = C[A[j]] + 1;
	}
	// 通过加总计算确定每一个i = 1,1,...,k,有多少个元素时小于i的
	cout<<"A中每个元素的个数:"<<endl;
	cout<<C[0]<<" ";
	for(int i = 1; i < k; i++)
	{
		C[i] = C[i] + C[i-1];
		cout<<C[i]<<" ";
	}
	cout<<endl;
	//把每个元素A[j]放在输出数组B中的正确位置上。
	for(int j = 20; j > 0; j--)
	{
		B[C[A[j]]] = A[j];
		C[A[j]] = C[A[j]]-1;
	}
	cout<<endl;
	delete [] C;
}

排序结果:


首先,计数排序不是一个比较算法。其次,计数排序在运行是需要申请两个额外的空间。当A中的元素非常大且稀疏时,C中空间就会浪费,同时,如果A的规模很大时,其实不适用计数排序。但是,计数排序有一个重要的性质,就是,它是稳定的排序。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值