探索 Sort.h:多功能排序算法模板库
在算法的世界里,排序算法是基础且关键的一部分。无论是处理大规模数据,还是进行简单的列表整理,合适的排序算法都能让我们的程序高效运行。今天,我要向大家介绍一个我自己写的强大的排序算法模板库 ——Sort.h
,它提供了 10 种不同的排序算法,能满足各种场景下的排序需求。
一、Sort.h
概述
Sort.h
是一个用 C++ 编写的模板类库,它封装了多种常见的排序算法。这个库的核心是一个模板类 Sort
,它可以处理不同数据类型的排序任务,只要这些数据类型支持 <
、>
、=(含拷贝构造)和 ==
运算符。通过这个库,我们可以方便地选择不同的排序算法,并指定排序的顺序(升序或降序)。
二、核心功能
1. 多种排序算法支持
Sort.h
提供了以下 10 种排序算法:
- 快速排序(Quick Sort):平均时间复杂度为 O(nlogn),在大规模随机数据上表现出色。
- 归并排序(Merge Sort):时间复杂度稳定在 O(nlogn),并且是稳定排序算法。
- 迭代归并排序(Iterative Merge Sort):避免了递归调用的栈开销,同样适用于大规模数据。
- 冒泡排序(Bubble Sort):简单易懂,适合小规模数据或接近有序的数据。
- 选择排序(Selection Sort):每次选择最小(或最大)元素,空间复杂度为 O(1)。
- 插入排序(Insertion Sort):在小规模数据或接近有序的数据上效率较高。
- 希尔排序(Shell Sort):对插入排序的改进,性能优于简单的插入排序。
- 简单计数排序(Easy Counting Sort):适用于非负整数的排序,时间复杂度为 O(n+k)。
- 计数排序(Counting Sort):适用于非负整数的排序,通过偏移量处理更广泛的数据范围。
- 基数排序(Radix Sort):按位排序,适合处理非负整数数据,时间复杂度接近线性。
2. 灵活的排序顺序
Sort
类的构造函数允许我们指定排序顺序,通过 isAscending
参数,我们可以轻松实现升序或降序排序。
3. 模板类设计
由于采用了模板类设计,Sort.h
可以处理不同数据类型的排序任务,提高了代码的复用性。
三、模板库完整代码(复制即用)
//Sort.hpp
#pragma once
#include<functional>/*** @brief 排序模板类,支持多种排序算法,可指定升序或降序* @tparam Data 待排序数据类型,该类型需要重载 <、>、== 、=(及拷贝构造)运算符以支持比较操作*/
template<class Data>
class Sort
{public:/*** @brief 比较函数指针类型,用于指向具体的比较函数* @param Data 第一个比较元素* @param Data 第二个比较元素* @return bool 比较结果(满足排序条件返回true,否则返回false)*/using PCompare = bool (*)(Data, Data);/*** @brief 构造函数,初始化排序相关参数* @param data 指向待排序数组的指针* @param size 待排序数组的元素个数* @param isAscending 排序方式(true为升序,false为降序,默认升序)*/Sort(Data* data, int size, bool isAscending = true);/*** @brief 快速排序接口*/void sort_quick();/*** @brief 归并排序接口*/void sort_merge();/*** @brief 迭代归并排序接口*/void sort_merge_iter();/*** @brief 冒泡排序接口*/void sort_bubble();/*** @brief 选择排序接口*/void sort_select();/*** @brief 插入排序接口*/void sort_insert();/*** @brief 希尔排序接口*/void sort_shell();/*** @brief 计数排序(简化版)接口(直接寻址表排序)*/void sort_count_easy();/*** @brief 计数排序接口*/void sort_count();/*** @brief 基数排序接口*/void sort_radix();
private:/*** @brief 归并操作的辅助函数,将两个有序数组合并为一个有序数组* @param c 存储合并结果的数组* @param d_size 结果数组的大小(冗余参数,实际为lena+lenb)* @param a 第一个有序数组* @param lena 第一个数组的长度* @param b 第二个有序数组* @param lenb 第二个数组的长度*/void _merge(Data* c, int d_size, Data* a, int lena, Data* b, int lenb);/*** @brief 快速排序的内部递归实现* @param data 待排序的子数组* @param start 子数组的起始索引(包含)* @param end 子数组的结束索引(包含)*/void _sort_quick(Data* data, int start, int end);/*** @brief 归并排序的内部递归实现* @param data 待排序的数组* @param size 待排序数组的元素个数*/void _sort_merge(Data* data, int size);/*** @brief 归并排序的内部递归实现* @param data 待排序的数组* @param size 待排序数组的元素个数*/void _merge_iter(Data* data, Data* temp, int left, int mid, int right);/*** @brief 判断第一个元素是否小于第二个元素(基于Data类型的<运算符)* @param t1 第一个比较元素* @param t2 第二个比较元素* @return bool 若t1 < t2返回true,否则返回false*/bool _isLess(Data t1, Data t2);/*** @brief 判断第一个元素是否大于第二个元素(基于Data类型的>运算符)* @param t1 第一个比较元素* @param t2 第二个比较元素* @return bool 若t1 > t2返回true,否则返回false*/bool _isGreater(Data t1, Data t2);/*** @brief 查找元素中的最大值* @param data 待排序的数组* @param size 待排序数组的元素个数*/int _findMax(Data* data, int size);int _findMin(Data* data, int size, Data maxVal);
private:Data* data; // 指向待排序数组的指针int size; // 待排序数组的元素个数bool isAscending; // 排序方向标志(true为升序,false为降序)PCompare p_com; // 指向比较函数的指针(根据排序方向动态绑定)
};/*** @brief 归并排序接口实现,调用内部递归函数*/
template<class Data>
void Sort<Data>::sort_merge()
{_sort_merge(data, size);
}/*** @brief 构造函数实现,初始化成员变量并设置比较函数* @note 升序时绑定_isLess函数,降序时绑定_isGreater函数*/
template<class Data>
Sort<Data>::Sort(Data* data, int size, bool isAscending)
{this->data = data;this->size = size;this->isAscending = isAscending;if (isAscending)//升序{p_com = isless;}else{p_com = isgreater;}this->isAscending = isAscending;
}/*** @brief 快速排序内部递归实现,采用挖坑法* @note 以区间首元素为基准,通过左右指针交换实现分区*/
template<class Data>
void Sort<Data>::_sort_quick(Data* data, int start, int end)
{// 终止条件:区间无效时直接返回if (start >= end) return;int pivot = data[start]; // 选取区间首元素作为基准值(优化点:可改用三数取中法)int left = start;int right = end;while (left < right) {// 从右向左找第一个小于基准的元素while (left < right && (p_com(pivot, data[right]) || data[right] == pivot)) right--;if (left < right) data[left++] = data[right]; // 移动基准坑到左边// 从左向右找第一个大于基准的元素while (left < right && (p_com(data[left], pivot) || data[right] == pivot)) left++;if (left < right) data[right--] = data[left]; // 移动基准坑到右边}// 基准值归位data[left] = pivot;// 递归排序左右子区间(注意边界检查)if (start < left - 1) _sort_quick(data, start, left - 1); // 左子区间至少2个元素if (left + 1 < end) _sort_quick(data, left + 1, end); // 右子区间至少2个元素
};/*** @brief 归并操作辅助函数,合并两个有序数组* @note 通过标记剩余元素减少循环次数,优化合并效率*/
template<class Data>
void Sort<Data>::_merge(Data* c, int d_size, Data* a, int lena, Data* b, int lenb)
{// 标记是否需要将数组 a 或 b 的剩余元素直接连接到结果数组 c 中bool IsConnect_a = false, IsConnect_b = false;// 分别作为数组 a、b 和 c 的索引int i = 0, j = 0, k = 0;// 当数组 a 和 b 都还有元素未处理时,进行比较合并操作while (i < lena && j < lenb) {if (p_com(a[i], b[j]) || a[i] == b[j]) {// 如果 a[i] 小于等于 b[j],则将 a[i] 放入结果数组 c 中if (i + 1 == lena) {// 如果数组 a 只剩下当前元素,标记需要将数组 b 的剩余元素连接到结果数组 c 中IsConnect_b = true;c[k++] = a[i++];// 跳出循环,因为后续可以直接处理数组 b 的剩余元素break;}else {// 正常将 a[i] 放入结果数组 c 中,并更新索引c[k++] = a[i++];}}else {// 如果 a[i] 大于 b[j],则将 b[j] 放入结果数组 c 中if (j + 1 == lenb) {// 如果数组 b 只剩下当前元素,标记需要将数组 a 的剩余元素连接到结果数组 c 中IsConnect_a = true;c[k++] = b[j++];// 跳出循环,因为后续可以直接处理数组 a 的剩余元素break;}else {// 正常将 b[j] 放入结果数组 c 中,并更新索引c[k++] = b[j++];}}}// 处理数组 a 或 b 中剩余的元素if (IsConnect_a) {// 如果标记为需要连接数组 a 的剩余元素,则将数组 a 剩余元素依次放入结果数组 c 中while (i < lena) c[k++] = a[i++];}else if (IsConnect_b) {// 如果标记为需要连接数组 b 的剩余元素,则将数组 b 剩余元素依次放入结果数组 c 中while (j < lenb) c[k++] = b[j++];}
}/*** @brief 归并排序内部递归实现,采用分治思想* @note 先将数组二分,递归排序子数组,最后合并有序子数组*/
template<class Data>
void Sort<Data>::_sort_merge(Data* data, int size)
{// 计算数组的中间位置int mid = size / 2;// 左子数组的长度int left = mid;// 右子数组的长度int right = size - mid;// 用于遍历原数组的索引int k = 0;// 动态分配内存给左子数组Data* a = new Data[left];// 初始化左子数组的元素为 0for (int i = 0; i < left; i++) a[i] = 0;// 动态分配内存给右子数组Data* b = new Data[right];// 初始化右子数组的元素为 0for (int j = 0; j < right; j++) b[j] = 0;// 将原数组 data 的前 left 个元素复制到左子数组 a 中for (int i = 0; i < left; i++) *(a + i) = *(data + k++);// 将原数组 data 的剩余元素复制到右子数组 b 中for (int j = 0; j < right; j++) *(b + j) = *(data + k++);// 如果左子数组的长度大于 1,递归调用 MergeSort 函数对左子数组进行排序if (left > 1) _sort_merge(a, left);// 如果右子数组的长度大于 1,递归调用 MergeSort 函数对右子数组进行排序if (right > 1) _sort_merge(b, right);// 调用 Merge 函数将排好序的左子数组和右子数组合并到原数组 data 中_merge(data, size, a, left, b, right);// 释放动态分配给左子数组的内存,避免内存泄漏delete[] a;// 释放动态分配给右子数组的内存,避免内存泄漏delete[] b;
}/*** @brief 快速排序接口实现,调用内部递归函数* @note 排序范围为整个数组(0到size-1)*/
template<class Data>
void Sort<Data>::sort_quick()
{_sort_quick(data, 0, size - 1);
}/*** @brief 冒泡排序实现,通过相邻元素比较交换完成排序* @note 每轮将最大/小元素"冒泡"到数组末尾*/
template<class Data>
void Sort<Data>::sort_bubble()
{//2,4,8,6,5,3,9,1,7for (int i = 0; i < size; i++){for (int j = 1; j < size - i; j++){if (p_com(data[j], data[j - 1])){Data temp = data[j - 1];data[j - 1] = data[j];data[j] = temp;}}}
}/*** @brief 选择排序实现,每轮选择最小/大元素放到指定位置* @note 通过索引记录目标元素位置,减少交换次数*/
template<class Data>
void Sort<Data>::sort_select()
{int index;Data temp;for (int i = 0; i < size - 1; i++){//查找index = i;for (int j = i + 1; j < size; j++){if (p_com(data[j], data[index]))index = j;}temp = data[i];data[i] = data[index];data[index] = temp;}
}/*** @brief 插入排序实现,将元素插入到已排序部分的合适位置* @note 从第二个元素开始,依次插入到左侧有序区间*/
template<class Data>
void Sort<Data>::sort_insert()
{int j;for (int i = 1; i < size; i++)//第一个本身就是有序的{//得到插入的数据Data temp = data[i];//右边数组i对应的的a[i]就是要插入的//把要插入数据之前的数组中需要移动版那个的部分后移一个下标for (j = i - 1; j >= 0 && p_com(temp, data[j]); j--)//左边有序数组倒序遍历,只要当前的a[j]比temp大,j就向前移动{data[j + 1] = data[j];//a[j+1]本质上就是a[i],即temp,所以覆盖掉不会丢失数据}//覆盖完以后data[j + 1] = temp;//运行到这一步时,//a[j] a[j+1] a[j+2] ---- a[j+2]==a[j+1]//相当于a[j+1]的值已经备份,可以直接用要插入的数据覆盖a[j+1]进行插入}
}/*** @brief 判断第一个元素是否小于第二个元素* @return bool 若t1 < t2返回true,否则返回false* @note 依赖Data类型的<运算符*/
template<class Data>
bool Sort<Data>::_isLess(Data t1, Data t2)
{return t1 < t2;
}/*** @brief 判断第一个元素是否大于第二个元素* @return bool 若t1 > t2返回true,否则返回false* @note 依赖Data类型的>运算符*/
template<class Data>
bool Sort<Data>::_isGreater(Data t1, Data t2)
{return t1 > t2;
}/*** @brief 归并排序接口实现,调用内部递归函数(迭代版)*/
template<class Data>
void Sort<Data>::sort_merge_iter() {if (size <= 1) return;Data* temp = new Data[size]; // 仅分配一次辅助数组// 自底向上合并:子数组长度从1开始,每次翻倍for (int step = 1; step < size; step *= 2) {// 按当前step合并相邻子数组for (int left = 0; left < size; left += 2 * step) {int mid = left + step - 1; // 左子数组终点int right = std::min(left + 2 * step - 1, size - 1); // 右子数组终点(避免越界)if (mid >= right) break; // 右子数组为空时跳过_merge_iter(data, temp, left, mid, right); // 合并[left,mid]和[mid+1,right]}}delete[] temp;
}// 迭代版合并函数(简化逻辑,复用辅助数组)
template<class Data>
void Sort<Data>::_merge_iter(Data* data, Data* temp, int left, int mid, int right) {int i = left, j = mid + 1, k = left;// 合并两个有序子数组到tempwhile (i <= mid && j <= right) {if (p_com(data[i], data[j])) {temp[k++] = data[i++];}else {temp[k++] = data[j++];}}// 处理剩余元素while (i <= mid) temp[k++] = data[i++];while (j <= right) temp[k++] = data[j++];// 从temp复制回原数组for (i = left; i <= right; i++) {data[i] = temp[i];}
}/*** @brief 希尔排序接口实现*/
template<class Data>
void Sort<Data>::sort_shell() {int step = size / 2;while (step > 0){for (int m = 0; m < step; m++){int j = 0;Data temp = 0;for (int i = m + step; i < size; i += step)//插入排序处理{temp = data[i];//要插入的数据for (j = i - step; j >= 0 && p_com(temp, data[j]); j -= step){data[j + step] = data[j];//元素后移}data[j + step] = temp;//插入元素}}step /= 2;}
}template<class Data>
int Sort<Data>::_findMax(Data* data, int size)
{int max = -1;for (int i = 0; i < size; i++){if (data[i] > 0){max = data[i] > max ? data[i] : max;}else{throw "基数排序中的数据必须为不重复的正整数";}}return max;
}template<class Data>
int Sort<Data>::_findMin(Data* data, int size,Data maxVal)
{int min = maxVal;for (int i = 0; i < size; i++){if (data[i] > 0){min = data[i] < min ? data[i] : min;}}return min;
}/*** @brief 计数排序(简化版)(直接寻址表排序)接口实现 请注意:不要有重复的数据和非正整数!*/
template<class Data>
void Sort<Data>::sort_count_easy()//计数排序_简化版
{//用一个数组存储数组a的值,存储在下标中,下标天然有序int maxSize = _findMax(data, size) + 1;Data* arr = new Data[maxSize];memset(arr, 0, sizeof(Data) * maxSize);for (int i = 0; i < size; i++){arr[data[i]] = data[i];//将数据值按下标存储}if (isAscending==true){int k = 0;for (int i = 0; i < maxSize; i++){if (arr[i] != 0)data[k++] = arr[i];}}else{int k = 0;for (int i = maxSize-1; i >=0;i--){if (arr[i] != 0)data[k++] = arr[i];}}delete[]arr;
}/*** @brief 计数排序接口实现 请注意:正整数!*/
template<class Data>
void Sort<Data>::sort_count()//计数排序_简化版
{//用一个数组存储数组a的值,存储在下标中,下标天然有序int maxVal = _findMax(data, size);int minVal = _findMin(data, size,maxVal);int maxSize = maxVal-minVal + 1;int basic_value = minVal;//基准参考数Data* arr = new Data[maxSize];memset(arr, 0, sizeof(Data) * maxSize);for (int i = 0; i < size; i++){arr[data[i]-basic_value]++;//下标arr[i]对应的值计数}if (isAscending == true){int k = 0;for (int i = 0; i < maxSize; i++){if (arr[i] != 0){for (int j = 0; j < arr[i]; j++){data[k++] = i + basic_value;//还原值}}}}else{int k = 0;for (int i = maxSize-1; i>=0; i--){if (arr[i] != 0){for (int j = arr[i]-1; j>=0 ; j--){data[k++] = i + basic_value;//还原值}}}}delete[]arr;
}/*** @brief 基数排序接口实现(LSD方式:从最低位到最高位)* @note 仅支持正整数排序,通过桶排序实现每一位的分组排序*/
template<class Data>
void Sort<Data>::sort_radix()
{if (size <= 1) return; // 边界条件:空数组或单个元素无需排序// 步骤1:找到最大值,确定最大位数int maxVal = _findMax(data, size);int maxDigits = 0;int tempVal = maxVal;while (tempVal > 0) {maxDigits++; // 统计最大位数(如1234有4位)tempVal /= 10;}// 步骤2:初始化10个桶(0-9,对应每一位的可能数字)// 用动态数组存储桶,每个桶是一个临时存储元素的数组Data** buckets = new Data * [10];int* bucketSizes = new int[10](); // 记录每个桶的元素数量,初始化为0// 步骤3:从最低位到最高位,逐位处理for (int exp = 1; maxVal / exp > 0; exp *= 10) { // exp:1(个位)、10(十位)、100(百位)...// 重置桶大小memset(bucketSizes, 0, sizeof(int) * 10);// 先为每个桶分配足够空间(最多为数组大小)for (int i = 0; i < 10; i++) {buckets[i] = new Data[size];}// 3.1 将元素按当前位的数字放入对应桶中for (int i = 0; i < size; i++) {int digit = (data[i] / exp) % 10; // 提取当前位的数字(0-9)buckets[digit][bucketSizes[digit]++] = data[i]; // 放入桶并更新计数}// 3.2 从桶中取出元素,按顺序放回原数组(根据排序方向调整桶的遍历顺序)int index = 0; // 原数组的索引if (isAscending) {// 升序:按0-9的桶顺序取元素for (int i = 0; i < 10; i++) {for (int j = 0; j < bucketSizes[i]; j++) {data[index++] = buckets[i][j];}}}else {// 降序:按9-0的桶顺序取元素for (int i = 9; i >= 0; i--) {for (int j = 0; j < bucketSizes[i]; j++) {data[index++] = buckets[i][j];}}}// 3.3 释放当前轮的桶内存for (int i = 0; i < 10; i++) {delete[] buckets[i];}}// 释放桶的指针数组delete[] buckets;delete[] bucketSizes;
}/*** @brief 说明:模板参数Data需要重载的运算符* 1. 小于运算符 < :用于_isLess函数的比较逻辑* 2. 大于运算符 > :用于_isGreater函数的比较逻辑* 3. 等于运算符 == :用于排序过程中相等元素的判断(如快速排序的基准比较)*/
四、代码示例
以下是一个简单的使用示例,展示了如何使用 Sort.h
进行排序:
#include”Sort.hpp“
#include<stdio.h>
#include<iostream>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
#define LENGTH 500
#define AREA LENGTH
#define M true
using namespace std;
template<class T>
void print(T a[], T len, const char* name)
{printf("----------------%s---------------\n", name);for (int i = 0; i < len; i++){cout << a[i] << " ";}puts("");
}
bool flag = true;
int main()
{cout << "数据基数:" << LENGTH << endl;int beginTime=0, endTime=0;int size = LENGTH;srand(timeGetTime());int a[LENGTH] = { 0 };for (int i = 0; i < LENGTH; i++) {a[i] = LENGTH-i+1;//0-999}int a1[LENGTH] = { 0 };memcpy(a1, a, LENGTH * sizeof(int));size = sizeof(a1) / sizeof(int);Sort<int> s1(a1, size,flag); beginTime = timeGetTime();s1.sort_bubble();endTime = timeGetTime();if (M)print <int> (a1, size, "冒泡排序");printf("%s耗费了%dms\n", "冒泡排序", endTime - beginTime);int a2[LENGTH] = { 0 };memcpy(a2, a, LENGTH*sizeof(int));size = sizeof(a2) / sizeof(int);Sort<int> s2(a2, size, flag);beginTime = timeGetTime();s2.sort_select();endTime = timeGetTime();if (M)print<int>(a2, size, "选择排序");printf("%s耗费了%dms\n", "选择排序", endTime - beginTime);int a3[LENGTH] = { 0 };memcpy(a3, a, LENGTH * sizeof(int));size = sizeof(a3) / sizeof(int);Sort<int> s3(a3, size, flag);beginTime = timeGetTime();s3.sort_insert();endTime = timeGetTime();if (M)print<int>(a3, size, "插入排序");printf("%s耗费了%dms\n", "插入排序", endTime - beginTime);int a4[LENGTH] = { 0 };memcpy(a4, a, LENGTH * sizeof(int));size = sizeof(a4) / sizeof(int);Sort<int> s4(a4, size, flag);beginTime = timeGetTime();s4.sort_quick();endTime = timeGetTime();if (M)print<int>(a4, size, "快速排序");printf("%s耗费了%dms\n", "快速排序", endTime - beginTime);int a5[LENGTH] = { 0 };memcpy(a5, a, LENGTH * sizeof(int));size = sizeof(a5) / sizeof(int);Sort<int> s5(a5, size, flag);beginTime = timeGetTime();s5.sort_merge();endTime = timeGetTime();if (M)print<int>(a5, size, "归并排序");printf("%s耗费了%dms\n", "归并排序", endTime - beginTime);int a6[LENGTH] = { 0 };memcpy(a6, a, LENGTH * sizeof(int));size = sizeof(a6) / sizeof(int);Sort<int> s6(a6, size, flag);beginTime = timeGetTime();s6.sort_merge_iter();endTime = timeGetTime();if (M)print<int>(a6, size, "迭代归并排序");printf("%s耗费了%dms\n", "迭代归并排序", endTime - beginTime);int a7[LENGTH] = { 0 };memcpy(a7, a, LENGTH * sizeof(int));size = sizeof(a7) / sizeof(int);Sort<int> s7(a7, size, flag);beginTime = timeGetTime();s7.sort_shell();endTime = timeGetTime();if (M)print<int>(a7, size, "希尔排序");printf("%s耗费了%dms\n", "希尔排序", endTime - beginTime);int a8[LENGTH] = { 0 };memcpy(a8, a, LENGTH * sizeof(int));size = sizeof(a8) / sizeof(int);Sort<int> s8(a8, size, flag);beginTime = timeGetTime();s8.sort_radix();endTime = timeGetTime();if (M)print<int>(a8, size, "基数排序");printf("%s耗费了%dms\n", "基数排序", endTime - beginTime);int a9[LENGTH] = { 0 };memcpy(a9, a, LENGTH * sizeof(int));size = sizeof(a9) / sizeof(int);Sort<int> s9(a9, size, flag);beginTime = timeGetTime();s9.sort_count();endTime = timeGetTime();if (M)print<int>(a9, size, "计数排序");printf("%s耗费了%dms\n", "计数排序", endTime - beginTime);return 0;
}
在这个示例中,我们创建了一个包含 5 个整数的数组,并使用 Sort
类的快速排序算法对其进行升序排序。最后,我们输出了排序后的数组。
四、算法选择建议
在实际应用中,我们需要根据数据的特点和具体需求来选择合适的排序算法。以下是一些建议:
- 大规模随机数据:快速排序或归并排序通常是不错的选择。
- 小规模数据:冒泡排序、选择排序或插入排序可能更合适。
- 接近有序的数据:插入排序的效率较高。
- 整数数据且取值范围较小:计数排序或基数排序可以提供线性时间复杂度。
五、总结
Sort.h
是一个功能强大、使用方便的排序算法模板库。它提供了多种排序算法,让我们可以根据不同的场景选择最合适的算法。无论是初学者学习排序算法,还是开发者处理实际项目中的排序任务,Sort.h
都是一个值得尝试的工具。
希望这篇介绍能让你对 Sort.h
有更深入的了解,如果你有任何问题或想法,欢迎在评论区留言讨论!(使用过程,若发现Bug,欢迎反馈)