非比较排序

非比较排序

一、什么是非比较排序


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

二、具体实现


1、计数排序


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

(1)代码实现

 1 void CountSort(int arr[], int size)
 2 {
 3 assert(arr);
 4 
 5 int min = arr[0], max = arr[0];//统计最大和最小的数
 6 for (int i = 0; i < size; i++)
 7 {
 8 if (arr[i] > max)
 9 {
10 max = arr[i];
11 }
12 if (arr[i] < min)
13 {
14 min = arr[i];
15 }
16 }
17 
18 int range = max - min + 1;//开空间的大小
19 int* count = new int[range]();
20 
21 memset(count, 0, sizeof(int)*range);
22 //统计次数
23 for (int i = 0; i < size; i++)
24 {
25 count[arr[i] - min]++;
26 }
27 
28 size_t index = 0;
29 for (int i = 0; i < range; i++)
30 {
31 while (count[i]-- != 0)
32 {
33 arr[index++] = i + min;
34 }
35 }
36 }


(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;
}

  

原文地址:https://www.cnblogs.com/muzhongjiang/p/12834276.html