欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计数排序

程序员文章站 2022-07-08 15:54:58
...

目录

 

计数排序

过程演示

代码


计数排序

输入n个元素,范围是0-k的整数,统计出0-k每个元素有多少个,反向遍历,对于每个元素a,统计出小于等于a的元素有几个,将a填充到对应的位置

一定要反向遍历,不然不稳定

过程演示

简单做了一个fgif,gif下面有图解

计数排序

假如我们有一个数组a[10],范围都是0-10的整数

index 0 1 2 3 4 5 6 7 8 9
a 7 7 6 0 9 0 5 6 7 8

先创建出一个数组c,遍历数组a,统计一下每个元素有多少个

index 0 1 2 3 4 5 6 7 8 9
c 2 0 0 0 0 1 2 3 1 1

对c求前缀和,对于每个i,小于等于i的元素有c[i]个

index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 8 9 10

创建一个临时数组b[10]用来输出最终结果,反向遍历数组a,对于每个元素a[i],小于等于a[i]的元素有c[a[i]]个,那么a[i]的最终位置是c[a[i]]-1(如果下标从1开始,那么最终位置就是c[a[i]])

i=8,a[i]=8,c[8]=9,小于等于8的元素有9个,所以b[8]=a[i]=8

index 0 1 2 3 4 5 6 7 8 9
b                 8  
index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 8 9 10

c[8]--,因为已经填充了一个,所以要-1

 

index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 8 8 10

i=7,a[i]=7,c[7]=8,小于等于7的元素有8个,所以b[7]=a[i]=7

index 0 1 2 3 4 5 6 7 8 9
b               7 8  
index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 8 9 10

c[7]--

index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 7 9 10

i=7,a[i]=6,c[6]=5,小于等于6的元素有5个,所以b[4]=a[i]=6

index 0 1 2 3 4 5 6 7 8 9
b         6     7 8  
index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 5 7 9 10

c[6]--

index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 4 7 9 10

i=6,a[i]=5,c[5]=3,小于等于5的元素有3个,所以b[2]=a[i]=5

index 0 1 2 3 4 5 6 7 8 9
b     5   6     7 8  
index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 3 4 7 9 10

c[5]--

index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 2 4 7 9 10

i=5,a[i]=0,c[0]=2,小于等于0的元素有2个,所以b[1]=a[i]=0

index 0 1 2 3 4 5 6 7 8 9
b   0 5   6     7 8  
index 0 1 2 3 4 5 6 7 8 9
c 2 2 2 2 2 2 4 7 9 10

c[0]--

index 0 1 2 3 4 5 6 7 8 9
c 1 2 2 2 2 2 4 7 9 10

i=4,a[i]=9,c[9]=10,小于等于9的元素有10个,所以b[9]=a[i]=9

index 0 1 2 3 4 5 6 7 8 9
b   0 5   6     7 8 9
index 0 1 2 3 4 5 6 7 8 9
c 1 2 2 2 2 2 4 7 9 10

c[9]--

index 0 1 2 3 4 5 6 7 8 9
c 1 2 2 2 2 2 4 7 9 9

i=3,a[i]=0,c[0]=3,小于等于0的元素有1个,所以b[0]=a[i]=0

index 0 1 2 3 4 5 6 7 8 9
b 0 0 5   6     7 8 9
index 0 1 2 3 4 5 6 7 8 9
c 1 2 2 2 2 2 4 7 9 9

c[0]--

index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 4 7 9 9

i=2,a[i]=6,c[6]=4,小于等于6的元素有4个,所以b[3]=a[i]=6

index 0 1 2 3 4 5 6 7 8 9
b 0 0 5 6 6     7 8 9
index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 4 7 9 9

c[6]--

index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 3 7 9 9

i=1,a[i]=7,c[7]=7,小于等于7的元素有7个,所以b[6]=a[i]=7

index 0 1 2 3 4 5 6 7 8 9
b 0 0 5 6 6   7 7 8 9
index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 3 7 9 9

c[7]--

index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 3 6 9 9

i=0,a[i]=7,c[7]=6,小于等于7的元素有6个,所以b[5]=a[i]=7

index 0 1 2 3 4 5 6 7 8 9
b 0 0 5 6 6 7 7 7 8 9
index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 3 6 9 9

c[7]--

index 0 1 2 3 4 5 6 7 8 9
c 0 2 2 2 2 2 3 5 9 9

代码

#include<iostream>
#include<cstring>
void countingSort(int a[], int n) {
	//找到最大的元素,如果知道范围就不用这一步了,直接开c数组就好了
	int maxNum = a[0];
	for (int i = 1; i < n; ++i)
		if (a[i] > maxNum)maxNum = a[i];
	int* c = new int[maxNum + 1];
	memset(c, 0, sizeof(int)*(maxNum + 1));
	//统计每个元素有几个
	for (int i = 0; i < n; ++i)++c[a[i]];
	//前缀和
	for (int i = 1; i <= maxNum; ++i)c[i] += c[i - 1];
	int* b = new int[n];
	//反向填充
	for (int i = n - 1; i >= 0; --i) {
		//两种实现
		/*
		第一种
		b[c[a[i]] - 1] = a[i];
		--c[i];*/

		//第二种
		b[--c[a[i]]] = a[i];
	}
	//复制回去
	memcpy(a, b, sizeof(int)*n);
	//for (int i = 0; i < n; ++i)a[i] = b[i];
	delete[] b;
	delete[] c;
}

时间复杂度,O(n+k)k是数组中的最大值

稳定性:稳定