1、九大常用排序算法介绍
在程序设计中,经常需要用到排序,可能大家都对排序算法有过一定的了解,不过,如果能系统地掌握它们,绝对是一件非常好的事情。
可能我们很熟悉冒泡排序、选择排序、快速排序、插入排序等等之类的排序算法,当被问到堆排序、归并排序等等就不知道怎么回事了。那么我们怎么去系统地记忆这些常用的排序算法呢?
我们可以根据排序的方式不同将排序算法分成插入排序、交换排序、选择排序、归并排序和基数排序,插入排序包含了直接插入排序、折半插入排序;交换排序包含了冒泡排序、快速排序;选择排序包含了直接选择排序、堆排序;可以结构图来记忆常用的这些排序算法,结构图如下:
2、算法的性能对比
3、算法的执行步骤与代码实现
(1)直接插入排序
/* 直接插入排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)选取无序区中第一个元素i (2)将i与有序区中元素j(0 <= j <= i-1)比较,寻找插入位置,同时移动元素 (3)将该元素插入合适位置 (4)重复(1)(2)(3)直至无序区长度为0 */ template<typename T> void InsertSort(T a[], int n) { for (int i = 1; i < n; i++) //每次选取无序区间的第一个元素插入 { T t = a[i]; int j = i - 1; //i - 1即为有序区最后一个元素 while (j >= 0 && t < a[j]) //边比较寻找插入位置边移动元素 { a[j + 1] = a[j]; j--; } a[j + 1] = t; //插入元素到有序区 } }
(2)折半插入排序
/* 折半插入排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)选取无序区中第一个元素i (2)在有序区间折半搜索该元素应该插入的位置 (3)将该元素插入合适位置 (4)重复(1)(2)(3)直至无序区长度为0 */ template<typename T> void BinaryInsertSort(T a[], int n) { for (int i = 1; i < n; i++) //每次选取无序区间的第一个元素插入 { T t = a[i]; int left = 0, right = i - 1; //折半寻找插入位置 while (left <= right) { int mid = (left + right) / 2; //取区间中间位置 if (t < a[mid]) right = mid - 1; //插入点在左半区 else left = mid + 1; //插入点在右半区(为保证排序稳定性,如果有元素相等,则在该元素后插入) } int j = i - 1; while (j >= right + 1) //移动元素 { a[j + 1] = a[j]; j--; } a[j + 1] = t; //插入元素到有序区 } }
(3)希尔排序
详细排序思路参考:https://www.cnblogs.com/chengxiao/p/6104371.html
/* 希尔排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)将待排序集合分成k个组,且每个组元素下标的差值为k (2)对每个组的元素进行直接插入排序 (3)减少组的规模(这里采用折半减少的方式),重复(1)(2)直至规模为最小值1 */ template<typename T> void ShellSort(T a[], int n) { int k = n / 2; //排序划分组数 while (k > 0) { for (int g = 0; g < k; g++) //对每组的元素分别进行插入排序 { for (int i = g + k; i < n; i += k) //插入排序 { T t = a[i]; int j = i - k; //将直接插入排序中的1换成k while (j >= 0 && t < a[j]) { a[j + k] = a[j]; j -= k; } a[j + k] = t; } } k = k / 2; //减少分组数,直至分组为0 } }
(4)冒泡排序
/* 冒泡排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)从无序区间的最后一个元素开始,如果该元素小于它相邻的前一个元素,则两者交换,重复比较直至无序区所有元素都比较完成 (2)将无序区间的第一个元素置入有序区间 (3)重复(1)(2)直至无序区间长度为0 */ template <typename T> void BubbleSort(T a[], int n) { for (int i = 0; i < n; i++) //区间[0, i]为有序区 { for (int j = n - 1; j > i; j--) //从无序区间的最后一个元素开始 { if (a[j] < a[j - 1]) //如果该元素小于它相邻的前一个元素,则两者交换 { T t = a[j]; a[j] = a[j - 1]; a[j - 1] = t; } } } }
(5)快速排序
/* 快速排序 a:待排序元素集合 left:集合中第一个元素下标 right:集合中最后一个元素下标 步骤: (1)以集合第一个元素为基准,进行划分,将小与它的元素放在它左边,将大于它的元素放在它右边 (2)将左边元素的区间、右边元素的区间递归进行划分 (3)重复(1)(2),直至子区间不能再划分为止 */ template <typename T> void QuickSort(T a[], int left, int right) { if (left >= right) return; //以第一个元素为基准,执行一趟划分 int i = left, j = right; T t = a[left]; while (i < j) { while (i < j && a[j] >= t) //从右向左扫描,选取第一个小于t的元素交换 j--; a[i] = a[j]; while (i < j && a[i] <= t) //再从左往右扫描,选取第一个大于t的元素交换 i++; a[j] = a[i]; } a[i] = t; //递归执行划分 QuickSort(a, left, i - 1); QuickSort(a, i + 1, right); }
(6)直接选择排序
/* 直接选择排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)从无序区间选择最小的元素置入有序区间 (2)重复(1)直至无序区间长度为0 */ template<typename T> void SelectSort(T a[], int n) { for (int i = 0; i < n; i++) { int imin = i; //标记无序区间最小元素下标 for (int j = i + 1; j < n; j++) //选出无序区间的最小元素 if (a[j] < a[imin]) imin = j; if (imin != i) //将选出的最小元素和无序区第一个元素交换 { T t = a[i]; a[i] = a[imin]; a[imin] = t; } } }
(7)堆排序
详细排序思路参考:https://www.cnblogs.com/chengxiao/p/6129630.html
/* 调整堆:给定一个非叶子节点,递归向下调整,使其满足堆的结构(根节点大于它的左右孩子节点) a:待排序元素集合 n:非叶子节点的下标 n:集合中元素的个数 步骤: (1)若左右孩子节点的最大值大于当前节点,将其和最大值的节点交换 (2)交换后可能会导致子树不满足堆的定义,所以要递归进行调整 */ template<typename T> void AdjustHeap(T a[], int i, int n) { T t = a[i]; int j = i * 2 + 1; //j指向i的左孩子节点 while (j < n) { if (j + 1 < n && a[j] < a[j + 1]) j++; //如果右子树大于它的左子树,则j改为指向右子树 if (t < a[j]) a[(j - 1) / 2] = a[j]; //如果孩子节点较大,则将孩子节点与父节点交换(因为是递归调整,所以不用修改孩子节点的值) else break; j = j * 2 + 1; //递归遍历孩子节点 } j < n ? a[j] = t : a[(j - 1) / 2] = t; //递归出口,被break掉的情况和j越界的情况 } /* 堆排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)建立堆 (2)每次取无序区堆顶元素,置入有序区 (3)调整堆 (4)重复(2)(3)直至无序区长度为0 */ template<typename T> void HeapSort(T a[], int n) { //构建堆 for (int i = n / 2 - 1; i >= 0; i--) //从第一个非叶子节点开始,向上调整堆直至调整至堆顶 AdjustHeap(a, i, n); //堆排序 for (int i = n - 1; i >= 0; i--) //每次选取堆顶元素置入有序区 { T t = a[0]; a[0] = a[i]; a[i] = t; AdjustHeap(a, 0, i); //调整堆 } }
(8)归并排序
详细排序思路参考:https://www.cnblogs.com/chengxiao/p/6194356.html
/* 归并排序 a:待排序元素集合 left:集合中第一个元素下标 right:集合中最后一个元素下标 步骤: (1)将排序集合递归划分成两个集合,直到划分集合的长度为1 (2)以有序的方式合并两个有序集合 (3)重复(2)直到所有集合都合并完 */ template<typename T> void MergeSort(T a[], int left, int right) { if (left < right) { //分 int mid = (left + right) / 2; //二分法将集合划分成两个部分 MergeSort(a, left, mid); //递归划分左边集合 MergeSort(a, mid + 1, right); //递归划分右边集合 //合 T *tmp = new T[right - left + 1]; //建立一个临时数组,存放合并的有序序列 int i = left, j = mid + 1, k = 0; //i为左边集合下标,j为右边集合下标,k为合并集合下标 while (i <= mid && j <= right) { if (a[i] < a[j]) tmp[k++] = a[i++]; //左边集合值更小 else tmp[k++] = a[j++]; //右边集合值更小 } while (i <= mid) tmp[k++] = a[i++]; //如果左边集合未遍历完 while (j <= right) tmp[k++] = a[j++]; //如果右边集合未遍历完 while (--k >= 0) a[left + k] = tmp[k]; //将临时数组拷贝回原数组 delete[] tmp; //释放空间 } }
(9)基数排序
/* 基数节点 val:元素的值,采用字符串表示 next:该元素的下一个节点地址 */ #include <string> typedef struct _RadixNode { string val; struct _RadixNode *next; }RadixNode; /* 基数排序 p:待排序元素集合,用单链表表示 r:元素的基数(对于二进制r为2,对于10进制r为10) d:元素的位数 步骤: (1)将集合分成r个组,r的值为集合每一位的所有可能取值的个数 (2)从集合的第d位开始,重复(3)(4)直至d的值为0,d的值为集合中元素的最大位数 (3)将集合中所有元素分配到相应的组 (4)从所有组中收集元素 */ void RadixSort(RadixNode *&p, int r, int d) { RadixNode **head = new RadixNode*[r]; //存储基数的每一个字符的头节点 RadixNode **tail = new RadixNode*[r]; //存储基数的每一个字符的尾节点 while (--d >= 0) //对集合中所有数字的每一位进行分配和收集 { //分配 for (int i = 0; i < r; i++) //初始化头结点和尾节点 head[i] = tail[i] = NULL; while (p != NULL) //分配集合中的每一个元素 { int i = p->val[d] - '0'; //获取元素第d位对应的字符下标 if (head[i] == NULL) //分配到对应的字符组,组中没有元素的情况 head[i] = tail[i] = p; else //分配到对应的字符组,组中已经有元素的情况 tail[i] = tail[i]->next = p; p = p->next; } //收集 p = NULL; auto q = p; for (int i = 0; i < r; i++) //收集每一个组的所有元素 { if (head[i] != NULL) //组不为空收集 { if (p == NULL) //还未收集到元素的情况 { p = head[i]; q = tail[i]; } else //已经收集到元素的情况 { q->next = head[i]; q = tail[i]; } } } if(q) q->next = NULL; //添加链表结束标志 } delete[] head, tail; //释放空间 }
3、测试
这里作者随机生成了20万个数据,数据的范围是0~10000,对上面提到的所有算法进行了时间复杂度的测试,测试代码和测试结果如下:
测试代码:
#include <Windows.h> #include <iostream> using namespace std; void InitRandSet(int a[], int n, int minVal, int maxVal) { int k = maxVal - minVal + 1; for (int i = 0; i < n; i++) a[i] = minVal + rand() % k; } void InitRadixData(RadixNode *&p, int a[], int n, int d) { auto *q = p; for (int i = 0; i < n; i++) { if (q == NULL) p = q = new RadixNode; else q = q->next = new RadixNode; q->val = to_string(a[i]); q->val = string(d - q->val.length(), '0') + q->val; } q->next = NULL; } int main() { const int n = 200000; //待排序集合长度 const int minVal = 0; //数据最小值,用于生成随机数据 const int maxVal = 10000; //数据最大值,用于生成随机数据 const int r = 10, d = 5; //基数排序参数d,r int *a = new int[n]; //待排序集合数组 int *aCopy = new int[n]; //集合数组备份,因为排序后数组会变为有序,所以需要备份无序数组 InitRandSet(aCopy, n, minVal, maxVal); //生成随机数组 RadixNode *p = NULL; //基数排序数据格式 InitRadixData(p, aCopy, n, d); //基数排序数据初始化 DWORD pre_time = GetTickCount(); //保存上一个时间 auto difTime = [&pre_time]()->long { //获取时间差 DWORD dif = GetTickCount() - pre_time; pre_time = GetTickCount(); return dif; }; auto copySet = [&a, aCopy, n]()->void { //拷贝数组 for (int i = 0; i < n; i++) a[i] = aCopy[i]; }; cout << "待排序集合长度:" << n << endl; //插入排序 copySet(); InsertSort(a, n); cout << "1.插入排序:" << difTime() << "ms" << endl; copySet(); BinaryInsertSort(a, n); cout << "2.折半插入排序:" << difTime() << "ms" << endl; copySet(); ShellSort(a, n); cout << "3.希尔排序:" << difTime() << "ms" << endl; //交换排序 copySet(); BubbleSort(a, n); cout << "4.冒泡排序:" << difTime() << "ms" << endl; copySet(); QuickSort(a, 0, n - 1); cout << "5.快速排序:" << difTime() << "ms" << endl; //选择排序 copySet(); SelectSort(a, n); cout << "6.选择排序:" << difTime() << "ms" << endl; copySet(); HeapSort(a, n); cout << "7.堆排序:" << difTime() << "ms" << endl; //归并排序 copySet(); MergeSort(a, 0, n - 1); cout << "8.归并排序:" << difTime() << "ms" << endl; //基数排序 RadixSort(p, r, d); cout << "9.基数排序:" << difTime() << "ms" << endl; delete[] a, aCopy; //释放资源 while (p != NULL) { auto q = p; p = p->next; delete q; } //释放链表申请的空间 while (1) cin.get(); return 0; }
测试结果:
完整代码:
#include <iostream> using namespace std; /* 直接插入排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)选取无序区中第一个元素i (2)将i与有序区中元素j(0 <= j <= i-1)比较,寻找插入位置,同时移动元素 (3)将该元素插入合适位置 (4)重复(1)(2)(3)直至无序区长度为0 */ template<typename T> void InsertSort(T a[], int n) { for (int i = 1; i < n; i++) //每次选取无序区间的第一个元素插入 { T t = a[i]; int j = i - 1; //i - 1即为有序区最后一个元素 while (j >= 0 && t < a[j]) //边比较寻找插入位置边移动元素 { a[j + 1] = a[j]; j--; } a[j + 1] = t; //插入元素到有序区 } } /* 折半插入排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)选取无序区中第一个元素i (2)在有序区间折半搜索该元素应该插入的位置 (3)将该元素插入合适位置 (4)重复(1)(2)(3)直至无序区长度为0 */ template<typename T> void BinaryInsertSort(T a[], int n) { for (int i = 1; i < n; i++) //每次选取无序区间的第一个元素插入 { T t = a[i]; int left = 0, right = i - 1; //折半寻找插入位置 while (left <= right) { int mid = (left + right) / 2; //取区间中间位置 if (t < a[mid]) right = mid - 1; //插入点在左半区 else left = mid + 1; //插入点在右半区(为保证排序稳定性,如果有元素相等,则在该元素后插入) } int j = i - 1; while (j >= right + 1) //移动元素 { a[j + 1] = a[j]; j--; } a[j + 1] = t; //插入元素到有序区 } } /* 希尔排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)将待排序集合分成k个组,且每个组元素下标的差值为k (2)对每个组的元素进行直接插入排序 (3)减少组的规模(这里采用折半减少的方式),重复(1)(2)直至规模为最小值1 */ template<typename T> void ShellSort(T a[], int n) { int k = n / 2; //排序划分组数 while (k > 0) { for (int g = 0; g < k; g++) //对每组的元素分别进行插入排序 { for (int i = g + k; i < n; i += k) //插入排序 { T t = a[i]; int j = i - k; //将直接插入排序中的1换成k while (j >= 0 && t < a[j]) { a[j + k] = a[j]; j -= k; } a[j + k] = t; } } k = k / 2; //减少分组数,直至分组为0 } } /* 冒泡排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)从无序区间的最后一个元素开始,如果该元素小于它相邻的前一个元素,则两者交换,重复比较直至无序区所有元素都比较完成 (2)将无序区间的第一个元素置入有序区间 (3)重复(1)(2)直至无序区间长度为0 */ template <typename T> void BubbleSort(T a[], int n) { for (int i = 0; i < n; i++) //区间[0, i]为有序区 { for (int j = n - 1; j > i; j--) //从无序区间的最后一个元素开始 { if (a[j] < a[j - 1]) //如果该元素小于它相邻的前一个元素,则两者交换 { T t = a[j]; a[j] = a[j - 1]; a[j - 1] = t; } } } } /* 快速排序 a:待排序元素集合 left:集合中第一个元素下标 right:集合中最后一个元素下标 步骤: (1)以集合第一个元素为基准,进行划分,将小与它的元素放在它左边,将大于它的元素放在它右边 (2)将左边元素的区间、右边元素的区间递归进行划分 (3)重复(1)(2),直至子区间不能再划分为止 */ template <typename T> void QuickSort(T a[], int left, int right) { if (left >= right) return; //以第一个元素为基准,执行一趟划分 int i = left, j = right; T t = a[left]; while (i < j) { while (i < j && a[j] >= t) //从右向左扫描,选取第一个小于t的元素交换 j--; a[i] = a[j]; while (i < j && a[i] <= t) //再从左往右扫描,选取第一个大于t的元素交换 i++; a[j] = a[i]; } a[i] = t; //递归执行划分 QuickSort(a, left, i - 1); QuickSort(a, i + 1, right); } /* 直接选择排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)从无序区间选择最小的元素置入有序区间 (2)重复(1)直至无序区间长度为0 */ template<typename T> void SelectSort(T a[], int n) { for (int i = 0; i < n; i++) { int imin = i; //标记无序区间最小元素下标 for (int j = i + 1; j < n; j++) //选出无序区间的最小元素 if (a[j] < a[imin]) imin = j; if (imin != i) //将选出的最小元素和无序区第一个元素交换 { T t = a[i]; a[i] = a[imin]; a[imin] = t; } } } /* 调整堆:给定一个非叶子节点,递归向下调整,使其满足堆的结构(根节点大于它的左右孩子节点) a:待排序元素集合 n:非叶子节点的下标 n:集合中元素的个数 步骤: (1)若左右孩子节点的最大值大于当前节点,将其和最大值的节点交换 (2)交换后可能会导致子树不满足堆的定义,所以要递归进行调整 */ template<typename T> void AdjustHeap(T a[], int i, int n) { T t = a[i]; int j = i * 2 + 1; //j指向i的左孩子节点 while (j < n) { if (j + 1 < n && a[j] < a[j + 1]) j++; //如果右子树大于它的左子树,则j改为指向右子树 if (t < a[j]) a[(j - 1) / 2] = a[j]; //如果孩子节点较大,则将孩子节点与父节点交换(因为是递归调整,所以不用修改孩子节点的值) else break; j = j * 2 + 1; //递归遍历孩子节点 } j < n ? a[j] = t : a[(j - 1) / 2] = t; //递归出口,被break掉的情况和j越界的情况 } /* 堆排序 a:待排序元素集合 n:集合中元素的个数 步骤: (1)建立堆 (2)每次取无序区堆顶元素,置入有序区 (3)调整堆 (4)重复(2)(3)直至无序区长度为0 */ template<typename T> void HeapSort(T a[], int n) { //构建堆 for (int i = n / 2 - 1; i >= 0; i--) //从第一个非叶子节点开始,向上调整堆直至调整至堆顶 AdjustHeap(a, i, n); //堆排序 for (int i = n - 1; i >= 0; i--) //每次选取堆顶元素置入有序区 { T t = a[0]; a[0] = a[i]; a[i] = t; AdjustHeap(a, 0, i); //调整堆 } } /* 归并排序 a:待排序元素集合 left:集合中第一个元素下标 right:集合中最后一个元素下标 步骤: (1)将排序集合递归划分成两个集合,直到划分集合的长度为1 (2)以有序的方式合并两个有序集合 (3)重复(2)直到所有集合都合并完 */ template<typename T> void MergeSort(T a[], int left, int right) { if (left < right) { //分 int mid = (left + right) / 2; //二分法将集合划分成两个部分 MergeSort(a, left, mid); //递归划分左边集合 MergeSort(a, mid + 1, right); //递归划分右边集合 //合 T *tmp = new T[right - left + 1]; //建立一个临时数组,存放合并的有序序列 int i = left, j = mid + 1, k = 0; //i为左边集合下标,j为右边集合下标,k为合并集合下标 while (i <= mid && j <= right) { if (a[i] < a[j]) tmp[k++] = a[i++]; //左边集合值更小 else tmp[k++] = a[j++]; //右边集合值更小 } while (i <= mid) tmp[k++] = a[i++]; //如果左边集合未遍历完 while (j <= right) tmp[k++] = a[j++]; //如果右边集合未遍历完 while (--k >= 0) a[left + k] = tmp[k]; //将临时数组拷贝回原数组 delete[] tmp; //释放空间 } } /* 基数节点 val:元素的值,采用字符串表示 next:该元素的下一个节点地址 */ #include <string> typedef struct _RadixNode { string val; struct _RadixNode *next; }RadixNode; /* 基数排序 p:待排序元素集合,用单链表表示 r:元素的基数(对于二进制r为2,对于10进制r为10) d:元素的位数 步骤: (1)将集合分成r个组,r的值为集合每一位的所有可能取值的个数 (2)从集合的第d位开始,重复(3)(4)直至d的值为0,d的值为集合中元素的最大位数 (3)将集合中所有元素分配到相应的组 (4)从所有组中收集元素 */ void RadixSort(RadixNode *&p, int r, int d) { RadixNode **head = new RadixNode*[r]; //存储基数的每一个字符的头节点 RadixNode **tail = new RadixNode*[r]; //存储基数的每一个字符的尾节点 while (--d >= 0) //对集合中所有数字的每一位进行分配和收集 { //分配 for (int i = 0; i < r; i++) //初始化头结点和尾节点 head[i] = tail[i] = NULL; while (p != NULL) //分配集合中的每一个元素 { int i = p->val[d] - '0'; //获取元素第d位对应的字符下标 if (head[i] == NULL) //分配到对应的字符组,组中没有元素的情况 head[i] = tail[i] = p; else //分配到对应的字符组,组中已经有元素的情况 tail[i] = tail[i]->next = p; p = p->next; } //收集 p = NULL; auto q = p; for (int i = 0; i < r; i++) //收集每一个组的所有元素 { if (head[i] != NULL) //组不为空收集 { if (p == NULL) //还未收集到元素的情况 { p = head[i]; q = tail[i]; } else //已经收集到元素的情况 { q->next = head[i]; q = tail[i]; } } } if(q) q->next = NULL; //添加链表结束标志 } delete[] head, tail; //释放空间 } #include <Windows.h> void InitRandSet(int a[], int n, int minVal, int maxVal) { int k = maxVal - minVal + 1; for (int i = 0; i < n; i++) a[i] = minVal + rand() % k; } void InitRadixData(RadixNode *&p, int a[], int n, int d) { auto *q = p; for (int i = 0; i < n; i++) { if (q == NULL) p = q = new RadixNode; else q = q->next = new RadixNode; q->val = to_string(a[i]); q->val = string(d - q->val.length(), '0') + q->val; } q->next = NULL; } int main() { const int n = 200000; //待排序集合长度 const int minVal = 0; //数据最小值,用于生成随机数据 const int maxVal = 10000; //数据最大值,用于生成随机数据 const int r = 10, d = 5; //基数排序参数d,r int *a = new int[n]; //待排序集合数组 int *aCopy = new int[n]; //集合数组备份,因为排序后数组会变为有序,所以需要备份无序数组 InitRandSet(aCopy, n, minVal, maxVal); //生成随机数组 RadixNode *p = NULL; //基数排序数据格式 InitRadixData(p, aCopy, n, d); //基数排序数据初始化 DWORD pre_time = GetTickCount(); //保存上一个时间 auto difTime = [&pre_time]()->long { //获取时间差 DWORD dif = GetTickCount() - pre_time; pre_time = GetTickCount(); return dif; }; auto copySet = [&a, aCopy, n]()->void { //拷贝数组 for (int i = 0; i < n; i++) a[i] = aCopy[i]; }; cout << "待排序集合长度:" << n << endl; //插入排序 copySet(); InsertSort(a, n); cout << "1.插入排序:" << difTime() << "ms" << endl; copySet(); BinaryInsertSort(a, n); cout << "2.折半插入排序:" << difTime() << "ms" << endl; copySet(); ShellSort(a, n); cout << "3.希尔排序:" << difTime() << "ms" << endl; //交换排序 copySet(); BubbleSort(a, n); cout << "4.冒泡排序:" << difTime() << "ms" << endl; copySet(); QuickSort(a, 0, n - 1); cout << "5.快速排序:" << difTime() << "ms" << endl; //选择排序 copySet(); SelectSort(a, n); cout << "6.选择排序:" << difTime() << "ms" << endl; copySet(); HeapSort(a, n); cout << "7.堆排序:" << difTime() << "ms" << endl; //归并排序 copySet(); MergeSort(a, 0, n - 1); cout << "8.归并排序:" << difTime() << "ms" << endl; //基数排序 RadixSort(p, r, d); cout << "9.基数排序:" << difTime() << "ms" << endl; delete[] a, aCopy; //释放资源 while (p != NULL) { auto q = p; p = p->next; delete q; } //释放链表申请的空间 while (1) cin.get(); return 0; }
参考资料:
[1] 李春葆.数据结构教程.清华大学出版社,2013.