计数排序的简单实现

计数排序的原理比较简单,但是很巧妙。有点类似于桶排序,但是有一些区别。

具体思想是,给定一个数组,先统计各个元素出现的次数,用元素的值做下标,得到一个新的数组。然后扫描这个数组,对于数组的每个下标,如果它对应的值不为零,说明原来数组中就有几个这样的值。由于下标的天然递增,依次将这些值展开就得到了排序后的数组。

但是计数排序有它的局限性,首先如果想用数组统计各个元素出现的次数,它的值必须是正整数。如果你想用map来统计次数的话,那么就无法保证下标的递增特性。(某些语言的map实现可能会自动按照下标排序,但复杂度就是另一回事了)。

最后,计数排序的复杂度是O(n+k),n为元素个数,k为最大值。代码如下:

// countSort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 

using namespace std;

vector countSort(vector& v)
{
	//找到最大值
	int max = -1000000;
	for (auto i : v)
		if (i >= max)
			max = i;
	
	//扫描一遍,记录各元素出现的次数
	vector c;
	c.resize(max + 1);
	for (auto i : v)
		c[i]++;

	//对出现的每个元素,按照其出现的次数,依次展开到目标数组
	vector ans;
	for (int i = 0; i < c.size(); i++)
	{
		if (c[i] != 0)
		{
			int temp = c[i];
			while (temp--)
				ans.push_back(i);
		}
	}
	return ans;
}

int main()
{
	vector a = { 8,2,4,9,3,6,100 };
	auto ans=countSort(a);
	for (auto i : ans)
		cout << i << endl;
	system("pause");
	return 0;
}

运行结果:

计数排序的简单实现_第1张图片

上面是按照我自己对计数排序的理解所写的代码。

CLRS中采用了另外一种方法。在的得到每个数出现次数的数组后,将这个数组的每个数加上它前面的一个数。这样得到的新数组中,每个元素表示小于等于某个数(也就是下标)的个数。举个栗子,比如说小于等于5的个数为6,则不管有几个总共有几个5,总会有最后一个5排在第5位(下标从0开始),这样算上剩下的小于等于5的那些数,总共达到了6个。这个地方稍微有点绕,不过这就是CLRS上关于计数排序的关键所在。因此我们可以用这个性质对原始数组中的元素再做一遍扫描,找到每个数的正确位置。代码如下:

// countSort.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 

using namespace std;

vector countSort(vector& v)
{
	//找到最大值
	int max = -1000000;
	for (auto i : v)
		if (i >= max)
			max = i;
	
	//扫描一遍,记录各元素出现的次数
	vector c;
	c.resize(max + 1);
	for (auto i : v)
		c[i]++;

	
	//对出现的每个元素,按照其出现的次数,依次展开到目标数组
	vector ans;
	for (int i = 0; i < c.size(); i++)
	{
		if (c[i] != 0)
		{
			int temp = c[i];
			while (temp--)
				ans.push_back(i);
		}
	}
	return ans;
}

vector countSort1(vector& v)
{
	//找到最大值
	int max = -1000000;
	for (auto i : v)
		if (i >= max)
			max = i;

	//扫描一遍,记录各元素出现的次数
	vector c;
	c.resize(max + 1);
	for (auto i : v)
		c[i]++;

	//小于等于每个数的个数
	for (int i = 1; i < c.size(); i++)
		c[i] += c[i - 1];

	vector ans;
	ans.resize(v.size());
	//for (int i = v.size() - 1; i >= 0; i--)
	for(int i=0;i a = { 8,2,4,9,3,6,100 };
	auto ans=countSort1(a);
	for (auto i : ans)
		cout << i << endl;
	system("pause");
	return 0;
}




你可能感兴趣的:(algorithm)