计数排序是用空间换取时间的算法,其假设n个输入元素中的每一个都在0到k区间内的一个整数,其中k为某个整数。当k=O(n)时,排序的运行时间为Theta(n)。
基本思想:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输出数组中的位置上了。
输入数组为A[1..n]
辅助数组:B[1..n]存放排序的输出,C[1..k]提供临时存储空间(存放A中数组元素值的出现次数)。
伪代码:
COUNTING-SORT(A,B,k)
let C[0..k] be a new array
for i = 0 to k //后面需要使用数组C来存储A中各元素的出现次数,所以需要清零操作
C[i] = 0
for j = 1 to A.length
C[A[j]] = C[A[j]] + 1 //统计A中各元素的出现次数存储在C中,C中下标为A中的元素值,与其对应的数组元素为出现次数,如C[1] = 0,即为“1”在A中的出现次数为0
for i = 1 to k
C[i] = C[i] + C[i-1] //计算A中小于等于i的一共有多少个,方便此后将i放在数组B中正确的位置上
for j = A.length downto 1
B[C[A[j]]] = A[j] //使用A中元素A[j]的出现次数作为B中的下标,把每个元素放在B中适当的位置
C[A[j]] = C[A[j]] -1 //在B中放入一个元素,与其对应C中出现的次数-1。这样,当遇到下一个等于A[j]的输入元素时,该元素可以被直接放到B中A[j]的前一位置上
12 3 4 5 6 7 80 1 2 3 4 51 2 3 4 5 6 7 8
A[2 5 3 0 2 3 0 3]C[2 2 4 7 7 8]B[3]
0 1 2 3 4 50 1 2 3 4 5
C[2 0 2 3 0 1]C[2 2 4 6 7 8]
(a)(b)(c)
1 2 3 4 5 6 7 81 2 3 4 5 6 7 81 2 3 4 5 6 7 8
B[03]B[03 3]B[0 0 2 2 3 3 3 5]
0 1 2 3 4 50 1 2 3 4 5
C[1 2 4 6 7 8]C[1 2 4 5 7 8]
(d)(e)(f)
步骤(a)为伪代码中第二个for循环,统计A中各元素的出现次数
步骤(b)为伪代码中第三个for循环,统计A中小于等于i元素的数量
步骤(c)(d)(e)为伪代码中第四个for循环,进行排序
步骤(f)为排序结果。
计数排序为稳定的排序算法,通常被用做基数排序算法的一个子过程,为了使基数排序能够正确运行,计数排序必须是稳定的。
计数排序Demo:
#include
#include
#include #define LENGTH 8
void counting_sort(int *A,int *B,int k)
{
int *C=(int *)malloc(k*sizeof(int));
for(int i = 0;
i < k;
i++)
C[i] = 0;
for(int i = 0;
i < LENGTH;
i++)
C[A[i]]++;
for(int i = 1;
i < k;
i++)//i应从1开始,若从0开始,则C[i-1]越界
C[i] = C[i] + C[i-1];
for(int i = LENGTH-1;
i >= 0;
i--)
{
B[C[A[i]]-1] = A[i];
//B数组的下标从0开始,C[A[i]]中的元素数量的总和从1开始计数,所以存放到B中时需要减1,才能放到正确的位置上 想象当A中只有一个元素,C[A[i]] = 1,要存放进B中,就是B[C[A[i]]-1]
C[A[i]]--;
}
free(C);
C = NULL;
}int main()
{
int A[LENGTH],B[LENGTH];
for(int i = 0;
i < LENGTH;
i++)
std::cin >> A[i];
//scanf("%d",A[i]);
counting_sort(A,B,6);
//k决定了数组中数的取值范围 0<=x<=k
for(int i = 0;
i < LENGTH;
i++)
printf("%d ",B[i]);
printf("\n");
system("pause");
return 0;
}
基数排序: 算法描述参照 算法总结系列之五: 基数排序(Radix Sort) -- Jeffrey Sun
radix_sort Demo:
【《算法导论》读书笔记--计数排序&基数排序】
#include
#include
#include
using namespace std;
#define LENGTH 4
#define NUM_LEN 3 //最大数位长度
void radix_sort(int *A,int d)
{
int sort_num = 0;
int B[LENGTH];
for(int j = 1;
j <= d;
j++)//d是总位数,位数由低到高进行排序
{
//计数排序部分
int p = (int)pow(10,j-1);
//用于A[i]/p%10 获取整个数组第j位的值,本轮是按照数组的第j位进行排序
int C[10];
//每一位的取值共有0-9十个情况
for(int i = 0;
i < 10;
i++)
C[i] = 0;
for(int i = 0;
i < LENGTH;
i++)
C[A[i]/p%10]++;
for(int i = 1;
i < 10;
i++)//i应从1开始
C[i] = C[i] + C[i-1];
for(int i = LENGTH-1;
i >= 0;
i--)
{
B[C[ A[i]/p%10 ]-1] = A[i];
//B数组的下标从0开始,C[A[i]]中的元素数量的总和从1开始计数,所以存放到B中时需要减1,才能放到正确的位置上 想象当A中只有一个元素,C[A[i]] = 1,要存放进B中,就是B[C[A[i]]-1]
C[A[i]/p%10]--;
}
//end
for(int i = 0;
i < LENGTH;
i++)//将本轮排序结果赋值回原数组
A[i] = B[i];
}
}int main()
{
int A[LENGTH];
for(int i = 0;
i < LENGTH;
i++)
cin >> A[i];
radix_sort(A,NUM_LEN);
for(int i = 0;
i < LENGTH;
i++)
cout << A[i] <<" ";
cout<
推荐阅读
- 人工智能|干货!人体姿态估计与运动预测
- 分析COMP122 The Caesar Cipher
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)
- C语言学习(bit)|16.C语言进阶——深度剖析数据在内存中的存储
- Python机器学习基础与进阶|Python机器学习--集成学习算法--XGBoost算法
- 数据结构与算法|【算法】力扣第 266场周赛
- 数据结构和算法|LeetCode 的正确使用方式
- leetcode|今天开始记录自己的力扣之路
- 人工智能|【机器学习】深度盘点(详细介绍 Python 中的 7 种交叉验证方法!)
- 网络|简单聊聊压缩网络