非比较排序

一、什么是非比较排序

区别传统的比较算法,不通过其中两个数的大小直接比较,来排序整个数列

二、具体实现

1、计数排序

很好理解,就是对应每个数我们统计每个数字出现的次数,然后用一个直接定址的哈希表来存放数据,在通过遍历这个哈希表,进而就可以排好序了

(1)代码实现

void CountSort(int arr[], int size)
{
	assert(arr);
	
	int min = arr[0], max = arr[0];//统计最大和最小的数
	for (int i = 0; i < size; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}

	int range = max - min + 1;//开空间的大小
	int* count = new int[range]();

	memset(count, 0, sizeof(int)*range);
	//统计次数
	for (int i = 0; i < size; i++)
	{
		count[arr[i] - min]++;
	}
	
	size_t index = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]-- != 0)
		{
			arr[index++] = i + min;
		}
	}
}

(2)优缺点
优点:对于密集无重复的序列,可以使用位图来节省空间

缺点:比较浪费空间,不能排序一些负数(通过一些特殊的处理其实是可以做到的,但是比较麻烦)

2、基数排序

包括LSD( Least Significant Digit first最低位优先)、MSD(Most Significant Digit first最高位优先)

其实两者的道理都是想通的,这里主要来讲解和实现LSD

(1)什么是基数排序

这里的基数是指数据的位数(个位、十位、百位...),LSD便是从个位到最高位(例如:最大的数为12345,那么最高位便为万位),每次由高从低到高进行排序。排完最高为之后,整个序列就变得有序了

思考:为什么排完最高位之后整个序列就变得有序了?

这是因为的由低位到高位进行排序,那么通过上一次的排序影响下一次的排序、简单的来说,就是处理千位的时候,对百位、十位、个位排好序的并没有影响,低位小的数据一定会在前面先处理掉,由相对位置来决定的·

(2)具体实现

void LSDSort(int arr[], int size)
{
	assert(arr);

	int maxRadix = GetMaxRadix(arr, size);
	int count[10] = { 0 };
	int start[10] = { 0 };
	int* bucket = new int[size];
	//有点像矩阵的那一块
	int radix = 1;
	for (int i = 0; i < maxRadix; ++i)//控制位数
	{
		memset(count, 0, sizeof(int) * 10);


		for (int j = 0; j < size; ++j)//统计对应的每次的低位相同的数字出现的次数
		{
			int num = (arr[j] / radix) % 10;//依次获取每一位的数字
			count[num]++;
		}
		start[0] = 0;//用来标记每相同低位的值到底有多少个,然后进行直接定位
		int index = 1;
		while (index < 10)
		{
			start[index] = start[index - 1] + count[index - 1];
			++index;
		}
		for (int k = 0; k < size; ++k)
		{
			int num = (arr[k] / radix) % 10;
			//关键
			bucket[start[num]++] = arr[k];//通过辅助的数组start直接进行定位
		}
		radix *= 10;
		memcpy(arr, bucket, sizeof(int)*size);

	}
	delete[] bucket;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值