【初阶数据结构题目】40. 计数排序

计数排序

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤:

  1. 统计相同元素出现次数

  2. 根据统计的结果将序列回收到原来的序列中

思路:

例如:{6,1,2,9,4,2,4,1,4}9个数

  1. 统计相同元素出现次数

6出现1次,1出现2次,2出现2次,9出现1次,4出现3

  1. 根据统计的结果将序列回收到原来的序列中

fca1a4c8a3578dc560a5c70715dbf4f6

定义一个i来遍历,i表示数组内元素

i先到0的位置,里面没有数据,不打印

然后到1的位置,里面有2,打印2

依次类推

最后打印结果:1 1 2 2 4 4 4 6 9


新数组的大小怎么确定?

利用原数组中最大的值来确定。创建max+1个空间的数组。

但这就会出现问题:比如有负数怎么办?比较{3, 4, 10000}呢?

如果把负数变成正数,取绝对值呢?也不行。因为正负数绝对值一样的情况下无法区分正负数。

那如果我们把负数统一加一个正数,让他变成整数呢?

我们可以让count=max-min+1

对于{-5,-5,9,5,1}

count=9-(-5)+1=15

创建数组,数组大小为15,下标为0-14

-5放在数组下标为0的位置中,这个位置元素为2

依此类推,下标-5就是原来的元素,这些元素和下标形成了映射关系。

fa7b858e7ef858bc2913b63473724b91

代码:

Sort.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include <assert.h>
#include <stdbool.h>
#include <memory.h>

//打印
void PrintArr(int* arr, int n);

//计数排序
void CountSort(int* arr, int n);

Sort.c

#include "Sort.h"

//打印
void PrintArr(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

//计数排序
void CountSort(int* arr, int n)
{
	//根据最大值最小值确定数组大小
	int max = arr[0], min = arr[0];
	for (int i = 1; i < n; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}

	int range = max - min + 1;//确定数组元素个数
	int* count = (int*)malloc(sizeof(int) * range);//创建数组
	//判断不为空
	if (count == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	//初始化count数组中所有的数据为0
	memset(count, 0, range * sizeof(int));//count的大小是range

	//例如{100,101,109,105,101,105}
	//min = 100,arr[i] - min就是count里面的下标
	//统计数组中每个数据出现的次数
	for (int i = 0; i < n; i++)
	{
		count[arr[i] - min]++;//这里的++是为了把次数放进去
	}

	//取count中的数据,往arr中放
	int index = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)//这里是为了把上面count对应次数给传进arr
		{
			arr[index++] = i + min;//表示arr数组的下标从0开始,存放数据
		}
	}
}

test.c

#include "Sort.h"

int main()
{
	int a[] = { 5, 3, 9, 6, 2, 4, 7, 1, 8 };
	int n = sizeof(a) / sizeof(int);
	printf("排序前:");
	PrintArr(a, n);

    CountSort(a, n);

	printf("排序后:");
	PrintArr(a, n);

	return 0;
}

计数排序的特性:

计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。 而且只能适用于整数排序,无法对小数排序。

时间复杂度:O(N + range)

空间复杂度:O(range)

稳定性:稳定

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值