数据结构与算法 —— 计数排序

计数排序

一、概念

基础概念:计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)

通俗理解:我们以前学习的排序(如:冒泡、快排…)都是基于比较的(就是在排序过程中需要不断的根据数的大小进行比较)。而计数排序,顾名思义,它是通过计算出现的次数来进行排序。

二、代码及过程

/**
*
*计数排序
*Date:2019年5月4日
*
***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void countSort(int *a,int n){
	int max = a[0];
	int min = a[0];
	// 1.找出当前数组中最大和最小元素
	for(int i = 1; i < n; i++){
		if(a[i] > max){
			max = a[i];
		}
		else if(a[i] < min){
			min = a[i];
		}
	}
	
	// 2.分配max-min+1的辅助数组空间(如:[5,15]范围内的数,就需要15-5+1的存储空间)
	int *temp = (int *)malloc(sizeof(int) * (max - min + 1));
	memset(temp,0,sizeof(int) * (max - min + 1));

	// 3.计数
	for(i = 0; i < n; i++){
		temp[a[i]-min]++;
	}

	// 4.排序原数组
	int sub = max - min;
	int k = 0;
	for(i = 0; i <= sub; i++){
		for(int j = 0; j < temp[i]; j++){
			a[k++] = i + min;
		}
	}
}

void show(int *a,int n){
	int i;
	for(i = 0; i < n; i++){
		printf("%3d",a[i]);
	}
}

void main(){
	int a[] = {7,8,5,9,12,15,6,9,6};
	int n = sizeof(a) / sizeof(a[0]);
	printf("\n排序前:\n");
	show(a,n);
	// 计数排序
	countSort(a,n);
	printf("\n排序后:\n");
	show(a,n);
	printf("\n");
}

三、复杂度

如果原数组的长度为n,最大值和最小值的差值为k,则:
时间复杂度: O(n + k)
空间复杂度: O(k)

四、其他

需注意:

  1. 如果最大值和最小值之差很大的话,那么使用计数排序反而效果更为低。
    (k值变得很大的话,O(n+k) 的时间复杂度还不如 O(nlogn),并且会浪费大量的存储空间)
    如: 对十个数进行排序,其中最大值为1亿,最小值为1。

  2. 计数排序不能对含有小数的数进行排序,如:0.34564、1.5454、0.66666…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值