排序算法之计数排序

原理:

假设待排序序列没有负数。对序列里面的所有元素,确定比该元素小的元素有几个。利用这个信息就能知道该元素应该放在哪个位置上。

举例:

1755239356
                     A序列(待排序)

0112031101
                     B序列(统计待排序的序列元素对应B下标的个数)

然后我们对B序列相邻两个元素进行相加,相加后的数字放在下标较大的位置里。

01244789910
                    B序列(相加后的结果,用于表示比A中元素小的元素个数)

然后我们对A序列逆序便利一下,结果放在C序列里面。

倒数第一个为6,找到B序列下标为6的位置,里面的值为8,说明这个元素应该排在第七个位置上。

       6  
                   C序列

B序列对应的第六个位置的元素-1。避免相同的数字。

01244779910
                   B序列

倒数第二个为5,找到B序列下标为5的位置,里面的值为7,说明这个元素应该排在第六个位置上。

      56  
                   C序列

B序列对应的第五个位置的元素-1。

01244679910
                     B序列

倒数第三个为3,找到B序列下标为3的位置,里面的值为4,说明这个元素应该排在第三个位置上。

   3  6  
                     C序列

B序列对应的第三个位置的元素-1。

01234679910
                        B序列

倒数第四个为9,找到B序列下标为9的位置,里面的值为10,说明这个元素应该排在第九个位置上。

   3  56 9
                       C序列

B序列对应的第九个位置的元素-1。

0123467999
                        B序列

倒数第五个为3,找到B序列下标为3的位置,里面的值为3,说明这个元素应该排在第二个位置上。

  33  56 9
                        C序列

B序列对应的第三个位置的元素-1。

0122467999
                         B序列

倒数第六个为2,找到B序列下标为2的位置,里面的值为2,说明这个元素应该排在第一个位置上。

 233  56 9
                         C序列

B序列对应的第二个位置的元素-1。

0112467999
                         B序列

倒数第七个为5,找到B序列下标为5的位置,里面的值为6,说明这个元素应该排在第五个位置上。

 233 556 9
                         C序列

B序列对应的第五个位置的元素-1。

0112457999
                          B序列

倒数第八个为5,找到B序列下标为5的位置,里面的值为5,说明这个元素应该排在第四个位置上。

 2335556 9
                           C序列

B序列对应的第五个位置的元素-1。

0112447999
                          B序列

倒数第九个为7,找到B序列下标为7的位置,里面的值为9,说明这个元素应该排在第八个位置上。

 233555679
                          C序列

B序列对应的第七个位置的元素-1。

0112447899
                         B序列

倒数第十个为1,找到B序列下标为1的位置,里面的值为1,说明这个元素应该排在第零个位置上。

1233555679
                         C序列(此时所有的元素已经排列完成)

B序列对应的第一个位置的元素-1。

0012447899
                         B序列

代码:

void CountSort(int a[], int nlen)
{
	int temp = a[0];
	for (int i = 0; i != nlen; ++i)
	{
		if (temp < a[i])
		{
			temp = a[i];
		}
	}
	int b_size = temp + 1;
	int *b = new int[b_size];
	for (int i = 0; i != b_size; ++i)
	{
		b[i] = 0;
	}
	for (int i = 0; i != nlen; ++i)
	{
		++b[a[i]];
	}
	for (int i = 1; i != b_size; ++i)
	{
		b[i] += b[i - 1];
	}
	int *c = new int[nlen];
	for (int i = nlen-1; i >= 0; --i)
	{
		c[--b[a[i]]] = a[i];
	}
	for (int i = 0; i != nlen; ++i)
	{
		a[i] = c[i];
	}
	delete[] b;
	b = nullptr;
	delete[] c;
	c = nullptr;
}


总结:

计数排序的思想很简单,并且是已常量时间完成的排序,时间复杂度为O(N),但是缺陷也很明显,其一,必须是大于等于0的元素,当有数字为负数的时候,可以给每个元素都加上一个正数,使得待排序序列为正数,排完后再减去这个正数(前提不越界的情况下)。其二,该排序算法浪费了大量的空间来换取时间。例如有99999的元素,那么B序列也应该有100000的长度。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值