前言
- 本篇博客主要介绍八大排序算法中的计数排序(CountSort)以及八大排序算法的总结分析
- 代码实现:C语言
导航🗺🌎🏁:
目录
计数排序
✨基本思想:
思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用,属于非比较排序。
🎆🎆实现步骤:
- 遍历待排数组,找出最大值max与最小值min
- 创建一个长度为max-min+1的数组
- 统计相同元素出现的次数放到一个新的数组中
- 根据统计的结果将序列按出现次数依次回写到原来的序列中
🎉🎉🎉代码如下:
void CountSort(int* a, int n) { int min = a[0], max = a[0]; for (int i = 1; i < n; ++i) { if (a[i] < min) min = a[i]; if (a[i] > max) max = a[i]; } // 统计次数的数组 int range = max - min + 1; int* count = (int*)malloc(sizeof(int) * range); if (count == NULL) { printf("malloc fail\n"); exit(-1); } memset(count, 0, sizeof(int) * range); // 统计次数 for (int i = 0; i < n; ++i) { count[a[i] - min]++; } // 回写-排序 int j = 0; for (int i = 0; i < range; ++i) { // 出现几次就会回写几个i+min while (count[i]--) { a[j++] = i + min; } } }
🔔🔔🔔🔔特性总结:
- 计数排序在数据范围集中时,效率很高,且仅适合整数,适用范围及场景有限。
- 时间复杂度:O(max(N, range))
- 空间复杂度:O(range)
- 稳定性:稳定
八大排序算法总结
✨排序分类及相关概念:
排序操作主要有八大排序算法:直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序
桶排序和基数排序,校招不考,这里不过多赘述。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。简单来说,由于待处理数据庞大,排序过程会通过硬盘进行存储数据。🍋稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
🎆🎆八大排序的实际运行效率对比:
主要通过下面的一个测试函数实现:// 测试排序的性能对比 void TestOP() { srand((unsigned int)time(0)); const int N = 10000; int* a1 = (int*)malloc(sizeof(int) * N); int* a2 = (int*)malloc(sizeof(int) * N); int* a3 = (int*)malloc(sizeof(int) * N); int* a4 = (int*)malloc(sizeof(int) * N); int* a5 = (int*)malloc(sizeof(int) * N); int* a6 = (int*)malloc(sizeof(int) * N); int* a7 = (int*)malloc(sizeof(int) * N); assert(a1 && a2 && a3 && a4 && a5 && a6 && a7); for (int i = 0; i < N; ++i) { a1[i] = rand(); a2[i] = a1[i]; a3[i] = a1[i]; a4[i] = a1[i]; a5[i] = a1[i]; a6[i] = a1[i]; a7[i] = a1[i]; } int begin1 = clock(); InsertSort(a1, N); int end1 = clock(); int begin2 = clock(); ShellSort(a2, N); int end2 = clock(); int begin3 = clock(); SelectSort(a3, N); int end3 = clock(); int begin4 = clock(); HeapSort(a4, N); int end4 = clock(); int begin5 = clock(); QuickSort(a5, 0, N - 1); int end5 = clock(); int begin6 = clock(); MergeSort(a6, N); int end6 = clock(); int begin7 = clock(); BubbleSort(a7, N); int end7 = clock(); printf("InsertSort:%d\n", end1 - begin1); printf("ShellSort:%d\n", end2 - begin2); printf("SelectSort:%d\n", end3 - begin3); printf("HeapSort:%d\n", end4 - begin4); printf("QuickSort:%d\n", end5 - begin5); printf("MergeSort:%d\n", end6 - begin6); printf("BubbleSort:%d\n", end7 - begin7); free(a1); free(a2); free(a3); free(a4); free(a5); free(a6); free(a7); }
🎉🎉🎉排序算法复杂度及稳定性分析:
复杂度及稳定性分析 排序算法 时间最坏 时间最好 空间复杂度 稳定性 直接插入排序 O(N^2) O(N) O(1) ✅ 希尔排序 平均:O(N^1.3) O(1) ❎ 直接选择排序 O(N^2) O(N^2) O(1) ❎ 堆排序 O(N*logN) O(N*logN) O(1) ❎ 冒泡排序 O(N^2) O(N) O(1) ✅ 快速排序 O(N^2)O(N*logN) O(logN) ❎ 归并排序 O(N*logN) O(N*logN) O(N) ✅ 因为有三数取中的存在,快速排序一般不会出现最好情况,所以综合来看,快排是当之无愧的Top1
学习记录:
- 📆本篇博客整理于2022.7.10
- 🎓作者:如何写出最优雅的代码
- 📑如有错误,敬请指正🌹🌹
- 🥂如果觉得写的不错,看完了别忘了点赞和收藏啊,感谢支持😏😏