非比较排序
非比较排序
一、什么是非比较排序
区别传统的比较算法,不通过其中两个数的大小直接比较,来排序整个数列
二、具体实现
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; }