当前位置:   article > 正文

九大排序算法汇总+性能分析实验报告(插入排序、希尔排序、折半插入排序、冒泡排序、归并排序、快速排序、基数排序、堆排序、选择排序)_排序算法对比分析实验

排序算法对比分析实验

一、实验目的和要求

1.熟练掌握九种排序算法原理和时间复杂度

2.综合比较各种排序算法时间性能

3.排序算法实验经验总结

二、实验内容与方法

1.插入排序

思路:从第一张开始拿牌,将这张牌前面的牌数比这张牌大的往后挪。
          没有比这张牌大的就放在这空隙中,那么到最后,每张牌前面的牌的大小都比自己小

步骤:
    用一个指针j代表他前面的牌,如果j这张牌比自己大,就让他往后面挪
    如果这张牌没自己大,就把自己放前面的牌后面(保证牌大小是从小到大)

插入排序代码

  1. void insertionSort(vector<int>& arr) {
  2. for (int i = 1; i < arr.size(); i++) {
  3. int key = arr[i];
  4. int j = i - 1;
  5. while (j >= 0 && arr[j] > key) {
  6. arr[j + 1] = arr[j];
  7. j--;
  8. }
  9. arr[j + 1] = key;
  10. }
  11. }

2.希尔排序(shell排序)

思路:先进行分组,不断细分。每组进行分别插入排序,这个算法优点是可以不用一位一位的移动并且减少逆序对数量
          越往后移动的次数越来越少,相较于一步一步移动,根据分组跳着移动,能够更快的移动到自己真正的位置

步骤:
    第一步分组,从每组n/2个数开始,每次每组大小除以二,直到每个组一个数,即朴素插入排序
    第二步从第gap到n每个数往回跳gap步,落脚点j就是他所在的分组,进行插入排序
    第三步重复一二步,在分成每个组一个数进行最后一次排序,即得到有序数列

shell排序代码

  1. void shellSort(vector<int>& arr) {
  2. int n = arr.size();
  3. for (int gap = n / 2; gap > 0; gap >>= 1) {
  4. for (int i = gap; i < n; i++) {
  5. int temp = arr[i];
  6. int j;
  7. for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
  8. arr[j + gap] = arr[j];
  9. }
  10. arr[j + gap] = temp;
  11. }
  12. }
  13. }

3.折半插入排序

思路:插牌的时候一张牌一张牌看太慢了,所以用眼睛找一下该插入的位置(二分做眼睛找位置)

折半插入排序代码

  1. void binaryInsertionSort(vector<int>& arr) {
  2. for (int i = 1; i < arr.size(); i++) {
  3. int key = arr[i];
  4. int left = 0, right = i - 1;
  5. while (left <= right) {
  6. int mid = (left + right) / 2;
  7. if (arr[mid] > key) {
  8. right = mid - 1;
  9. }
  10. else {
  11. left = mid + 1;
  12. }
  13. }
  14. for (int j = i - 1; j >= left; j--) { //将要找的位置的最右面数开始到找到的位置都往后挪,为插入的数腾位置
  15. arr[j + 1] = arr[j];
  16. }
  17. arr[left] = key;
  18. }
  19. }

4.冒泡排序

思路:每次都是将数组中最大的泡泡挪到最后
          若数组没发生挪动说明每个泡泡后面的泡泡都比他大

冒泡排序代码

  1. void bubbleSort(vector<int>& arr) {
  2. bool flag = true;
  3. for (int i = 0; i < arr.size() - 1 && flag; i++) {
  4. flag = false;
  5. for (int j = 0; j < arr.size() - i - 1; j++) {
  6. if (arr[j] > arr[j + 1]) {
  7. swap(arr[j], arr[j + 1]);
  8. flag = true;
  9. }
  10. }
  11. }
  12. }

5.归并排序

思路:先将每个数分到一个文件夹中,而后合并每两个文件夹,使合并后的大文件夹是有序的,最终合并到一个文件里

步骤:
    第一步将数列不断二分,分成小片段,对小片段进行操作
    第二步开出两个空间,分别存两个文件夹的数
    第三步为完成将两个空间(这两个空间数都是有序的)中最小的数提出了,放数组里。
          所以用两个指针i,j 分别比较两个空间内第一个数(即该空间最小数)将较小的放入数组,被放入的空间指针++
    第四步当有一个空间的数全都放入了数组里,则直接将剩余空间的所有数放入数组里
    当从小文件合并到大文件之后,就得到有序数列

归并排序代码

  1. void merge(vector<int>& arr, int l, int m, int r) {
  2. int n1 = m - l + 1;
  3. int n2 = r - m;
  4. vector<int> L(n1), R(n2);
  5. for (int i = 0; i < n1; i++) {
  6. L[i] = arr[l + i];
  7. }
  8. for (int j = 0; j < n2; j++) {
  9. R[j] = arr[m + 1 + j];
  10. }
  11. int i = 0, j = 0, k = l;
  12. while (i < n1 && j < n2) {
  13. if (L[i] <= R[j]) {
  14. arr[k] = L[i];
  15. i++;
  16. }
  17. else {
  18. arr[k] = R[j];
  19. j++;
  20. }
  21. k++;
  22. }
  23. while (i < n1) {
  24. arr[k] = L[i];
  25. i++;
  26. k++;
  27. }
  28. while (j < n2) {
  29. arr[k] = R[j];
  30. j++;
  31. k++;
  32. }
  33. }
  34. void mergeSort(vector<int>& arr, int l, int r) {
  35. if (l < r) {
  36. int m = l + (r - l) / 2;
  37. mergeSort(arr, l, m);
  38. mergeSort(arr, m + 1, r);
  39. merge(arr, l, m, r);
  40. }
  41. }

6.快速排序

思路:分治思想 保证每个数左边的数都比他小,右边的数都比他大

步骤:
    第一步让最后一个数成为基准privot
    第二步确认指针i,如果从开始到最后有数比基准小,交换指针指向的数和这个数,则i和i左边的数一定是小于基准的
    (刚开始arr[i]是最左边的数,将小于基准的数和arr[i]进行交换,即将小于基准的数放在左边)
    第三步将i+1位置与基准交换,则基准的左边一定是小于基准的,基准右边的一定是大于基准的
    第四步从调整整个数组的基准,到每个数都是基准(即确保每个数的左边小于基准,右边大于基准)得到有序数列

快速排序代码

  1. int partition(vector<int>& arr, int low, int high) {
  2. int pivot = arr[high];
  3. int i = low - 1;
  4. for (int j = low; j < high; j++) {
  5. if (arr[j] < pivot) {
  6. i++;
  7. swap(arr[i], arr[j]);
  8. }
  9. }
  10. swap(arr[i + 1], arr[high]);
  11. return i + 1;
  12. }
  13. void quickSort(vector<int>& arr, int low, int high) {
  14. if (low < high) {
  15. int pi = partition(arr, low, high);
  16. quickSort(arr, low, pi - 1);
  17. quickSort(arr, pi + 1, high);
  18. }
  19. }

7.基数排序

思路:用空间换时间,比较两个数是高位大小比低位大小更重要,
    所以我们低位开始,相同位层进行排序,后面操作影响前面排序顺序即高位重要性高于低位,
    每个位层的排序为一个轮次,排序到最后就得到了有序

步骤:
    第一步找到最高位,求出轮次的次数
    第二步开出一个备用空间用来存每个轮次的结果 
    第三步开出十个桶进行位层排序,将这些数进行重要性分级
    第四步求前缀和,画出分区,将不同重要级区分开来
    第五步将桶中的数存进备用空间
    第六步更新数组
    第七步重复三四五六步得到有序数列

基数排序代码

  1. void countSort(vector<int>& arr, int exp) {
  2. int n = arr.size();
  3. vector<int> output(n);
  4. vector<int> count(10, 0);
  5. for (int i = 0; i < n; i++) {
  6. count[(arr[i] / exp) % 10]++;
  7. }
  8. for (int i = 1; i < 10; i++) {
  9. count[i] += count[i - 1];
  10. }
  11. for (int i = n - 1; i >= 0; i--) {
  12. output[count[(arr[i] / exp) % 10] - 1] = arr[i];
  13. count[(arr[i] / exp) % 10]--;
  14. }
  15. for (int i = 0; i < n; i++) {
  16. arr[i] = output[i];
  17. }
  18. }
  19. void radixSort(vector<int>& arr) {
  20. int maxVal = *max_element(arr.begin(), arr.end());
  21. for (int exp = 1; maxVal / exp > 0; exp *= 10) {
  22. countSort(arr, exp);
  23. }
  24. }

8.堆排序

思路:利用堆的性质找到最大值,再用选择排序原理进行排序

步骤:
    第一步先构建堆结构(根的值最大,每个节点一定是他那个子树的最大值,但不和同层的有什么关系)
    第二步将根(最大值)与最后一个元素交换,使得保证最后的节点是最大值
    第三步将被交换的元素放回堆里,使得剩余元素再次构成堆结构,保证根是最大值
    第四步 循环二三步,使得从最后到开始是从大到小,即得到开始到结束是从小到大

堆排序代码

  1. void heapify(vector<int>& arr, int n, int i) {
  2. int largest = i;
  3. int l = 2 * i + 1;
  4. int r = 2 * i + 2;
  5. if (l < n && arr[l] > arr[largest]) {
  6. largest = l;
  7. }
  8. if (r < n && arr[r] > arr[largest]) {
  9. largest = r;
  10. }
  11. if (largest != i) {
  12. swap(arr[i], arr[largest]);
  13. heapify(arr, n, largest);
  14. }
  15. }
  16. void treeSelectionSort(vector<int>& arr) {
  17. int n = arr.size();
  18. for (int i = n / 2 - 1; i >= 0; i--) {
  19. heapify(arr, n, i);
  20. }
  21. for (int i = n - 1; i > 0; i--) {
  22. swap(arr[0], arr[i]);
  23. heapify(arr, i, 0);
  24. }
  25. }

9.选择排序

思路:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。重复第二步,直到所有元素均排序完毕。

选择排序代码

  1. void selectionSort(vector<int>& arr) {
  2. int n = arr.size();
  3. for (int i = 0; i < n - 1; i++) {
  4. int minIndex = i;
  5. for (int j = i + 1; j < n; j++) {
  6. if (arr[j] < arr[minIndex]) {
  7. minIndex = j;
  8. }
  9. }
  10. swap(arr[i], arr[minIndex]);
  11. }
  12. }

三、实验步骤和过程

1.算法性能分析

 说明:通过C++语言实现多种排序方式,分别对这些排序算法进行测试。记录数据与绘制对数图表如下。本实验选取的理论值基准均为数据规模为1000000时的测试数据。 但由于设备能力有限,数据来源于其他博客,本文附上的代码只是简单的对比各个排序算法在100000数据量时的运行时间对比,让读者能够更直观的看到各个排序算法时间复杂度方面的差距,从而更好的理解这些算法。

理论上各个算法的时间复杂度、空间复杂度和稳定性如下表,其中堆排序、快速排序和归并排序复杂度是(n\log_2 n)较为优秀,在一定情况下基数排序的速度出奇快,但是他的条件更为苛刻,适用面相较于其他更窄。其他时间复杂度是(n^2)主要是思路简单,代码量少,但对大数据实用性差。

(图片来源:https://blog.csdn.net/ytusdc/article/details/102528482)

2.算法对比分析

实验步骤:分别对各个排序算法进行运行时间的测量,数据规模从10-1000000。通过记录每个算法运行的时间,记录成表格,绘制成折线图。来更直观的比对每种排序算法的时间复杂度优劣,进而分析其优缺点。

冒泡排序插入排序折半插入排序希尔排序归并排序堆排序快速排序基数排序选择排序
100.00050.00040.00040.000533.40E-060.000171.00E-080.000274.00E-04
1000.001050.00150.00130.00212.60E-050.001051.00E-080.000391.30E-03
10000.004580.003050.001850.006040.00030.00160.0000950.0005650.00205
100000.47130.111150.07890.013950.0080.00240.001450.003040.0915
10000046.271710.12056.69590.05560.12460.04070.01780.02569.6635
10000004569.761059.13736.4410.67441.308950.42470.208350.1802921.265

(图片原创)

根据图表可以将这几个排序算法分成三类:

        第一类,简单排序。即冒泡、选择和插入排序。这几种排序方法的优点在于简单直观,代码好写,并且在数据规模较小时运算速度有些微优势。缺点在于,当数据规模增大时,简单排序的耗时会很快增加到令人难以忍受的程度。因此,这三种排序算法适用于数据规模小的情况。推荐插入排序和选择排序。

        第二类,希尔排序、归并排序和堆排序。这三种排序的时间复杂度优于O(n^2).可以应对较多情况。 

        第三类,快速排序、基数排序和计数排序。基数排序和计数排序时间复杂度到达线性级别。而快速排序复杂度中隐含的常数因子很小,是(n\log_2n)复杂度级别中最快的一种排序方法。这三种排序方法速度极快,然而空间占用较高(归并排序也有空间占用的问题),并且对待排序数据有要求(快排数据不能是顺序的,基数排序需要数据有基数,基数排序需要数据可以计数)。在数据规模特别大时,需要考虑空间复杂度的问题。

四、实验结论和体会

实验结论:在处理小规模数据排序问题时,插入排序和选择排序是较好的选择,冒泡排序也是可选的算法。在数据规模较大时,应该选择希尔排序、堆排序、归并排序、快速排序、基数排序或基数排序。并且,数据规模大时,若采用归并排序、快速排序、基数排序或计数排序,需要考虑空间复杂度的问题。

实验体会:我们需要应对不同情况使用不同的排序算法。待排序数据的规模,极差,类型和基础有序度,都是我们选择排序算法时需要考虑的东西。不同的排序算法适合不同的数据,当我们遇到问题时不要只盯着一种排序算法用,还需要考虑数据性质。

五、实验代码

  1. //大作业:八大排序算法( 插入排序 希尔排序 折半插入排序 树形选择排序 冒泡排序
  2. // 归并排序 快速排序 基数排序)
  3. #include <iostream>
  4. #include <chrono>
  5. #include <random>
  6. #include <vector>
  7. #include <algorithm>
  8. using namespace std;
  9. // 插入排序
  10. /*
  11. 思路:从第一张开始拿牌,将这张牌前面的牌数比这张牌大的往后挪。
  12. 没有比这张牌大的就放在这空隙中,那么到最后,每张牌前面的牌的大小都比自己小
  13. 用一个指针j代表他前面的牌,如果j这张牌比自己大,就让他往后面挪
  14. 如果这张牌没自己大,就把自己放前面的牌后面(保证牌大小是从小到大)
  15. */
  16. void insertionSort(vector<int>& arr) {
  17. for (int i = 1; i < arr.size(); i++) {
  18. int key = arr[i];
  19. int j = i - 1;
  20. while (j >= 0 && arr[j] > key) {
  21. arr[j + 1] = arr[j];
  22. j--;
  23. }
  24. arr[j + 1] = key;
  25. }
  26. }
  27. // 希尔排序
  28. /*
  29. 思路:先进行分组,不断细分。每组进行分别插入排序,这个算法优点是可以不用一位一位的移动并且减少逆序对数量
  30. 越往后移动的次数越来越少,相较于一步一步移动,根据分组跳着移动,能够更快的移动到自己真正的位置
  31. 第一步分组,从每组n/2个数开始,每次每组大小除以二,直到每个组一个数,即朴素插入排序
  32. 第二步从第gap到n每个数往回跳gap步,落脚点j就是他所在的分组,进行插入排序
  33. 第三步重复一二步,在分成每个组一个数进行最后一次排序,即得到有序数列
  34. */
  35. void shellSort(vector<int>& arr) {
  36. int n = arr.size();
  37. for (int gap = n / 2; gap > 0; gap >>= 1) {
  38. for (int i = gap; i < n; i++) {
  39. int temp = arr[i];
  40. int j;
  41. for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
  42. arr[j + gap] = arr[j];
  43. }
  44. arr[j + gap] = temp;
  45. }
  46. }
  47. }
  48. // 折半插入排序
  49. /*
  50. 思路:插牌的时候一张牌一张牌看太慢了,所以用眼睛找一下该插入的位置(二分做眼睛找位置)
  51. */
  52. void binaryInsertionSort(vector<int>& arr) {
  53. for (int i = 1; i < arr.size(); i++) {
  54. int key = arr[i];
  55. int left = 0, right = i - 1;
  56. while (left <= right) {
  57. int mid = (left + right) / 2;
  58. if (arr[mid] > key) {
  59. right = mid - 1;
  60. }
  61. else {
  62. left = mid + 1;
  63. }
  64. }
  65. for (int j = i - 1; j >= left; j--) { //将要找的位置的最右面数开始到找到的位置都往后挪,为插入的数腾位置
  66. arr[j + 1] = arr[j];
  67. }
  68. arr[left] = key;
  69. }
  70. }
  71. // 冒泡排序
  72. /*
  73. 思路:每次都是将数组中最大的泡泡挪到最后
  74. 若数组没发生挪动说明每个泡泡后面的泡泡都比他大
  75. */
  76. void bubbleSort(vector<int>& arr) {
  77. bool flag = true;
  78. for (int i = 0; i < arr.size() - 1 && flag; i++) {
  79. flag = false;
  80. for (int j = 0; j < arr.size() - i - 1; j++) {
  81. if (arr[j] > arr[j + 1]) {
  82. swap(arr[j], arr[j + 1]);
  83. flag = true;
  84. }
  85. }
  86. }
  87. }
  88. // 归并排序
  89. /*
  90. 思路:先将每个数分到一个文件夹中,而后合并每两个文件夹,使合并后的大文件夹是有序的,最终合并到一个文件里
  91. 第一步将数列不断二分,分成小片段,对小片段进行操作
  92. 第二步开出两个空间,分别存两个文件夹的数
  93. 第三步为完成将两个空间(这两个空间数都是有序的)中最小的数提出了,放数组里。
  94. 所以用两个指针i,j 分别比较两个空间内第一个数(即该空间最小数)将较小的放入数组,被放入的空间指针++
  95. 第四步当有一个空间的数全都放入了数组里,则直接将剩余空间的所有数放入数组里
  96. 当从小文件合并到大文件之后,就得到有序数列
  97. */
  98. void merge(vector<int>& arr, int l, int m, int r) {
  99. int n1 = m - l + 1;
  100. int n2 = r - m;
  101. vector<int> L(n1), R(n2);
  102. for (int i = 0; i < n1; i++) {
  103. L[i] = arr[l + i];
  104. }
  105. for (int j = 0; j < n2; j++) {
  106. R[j] = arr[m + 1 + j];
  107. }
  108. int i = 0, j = 0, k = l;
  109. while (i < n1 && j < n2) {
  110. if (L[i] <= R[j]) {
  111. arr[k] = L[i];
  112. i++;
  113. }
  114. else {
  115. arr[k] = R[j];
  116. j++;
  117. }
  118. k++;
  119. }
  120. while (i < n1) {
  121. arr[k] = L[i];
  122. i++;
  123. k++;
  124. }
  125. while (j < n2) {
  126. arr[k] = R[j];
  127. j++;
  128. k++;
  129. }
  130. }
  131. void mergeSort(vector<int>& arr, int l, int r) {
  132. if (l < r) {
  133. int m = l + (r - l) / 2;
  134. mergeSort(arr, l, m);
  135. mergeSort(arr, m + 1, r);
  136. merge(arr, l, m, r);
  137. }
  138. }
  139. // 快速排序
  140. /*
  141. 思路:分治思想 保证每个数左边的数都比他小,右边的数都比他大
  142. 第一步让最后一个数成为基准privot
  143. 第二步确认指针i,如果从开始到最后有数比基准小,交换指针指向的数和这个数,则i和i左边的数一定是小于基准的
  144. (刚开始arr[i]是最左边的数,将小于基准的数和arr[i]进行交换,即将小于基准的数放在左边)
  145. 第三步将i+1位置与基准交换,则基准的左边一定是小于基准的,基准右边的一定是大于基准的
  146. 第四步从调整整个数组的基准,到每个数都是基准(即确保每个数的左边小于基准,右边大于基准)得到有序数列
  147. */
  148. int partition(vector<int>& arr, int low, int high) {
  149. int pivot = arr[high];
  150. int i = low - 1;
  151. for (int j = low; j < high; j++) {
  152. if (arr[j] < pivot) {
  153. i++;
  154. swap(arr[i], arr[j]);
  155. }
  156. }
  157. swap(arr[i + 1], arr[high]);
  158. return i + 1;
  159. }
  160. void quickSort(vector<int>& arr, int low, int high) {
  161. if (low < high) {
  162. int pi = partition(arr, low, high);
  163. quickSort(arr, low, pi - 1);
  164. quickSort(arr, pi + 1, high);
  165. }
  166. }
  167. // 基数排序
  168. /*
  169. 思路:用空间换时间,比较两个数是高位大小比低位大小更重要,
  170. 所以我们低位开始,相同位层进行排序,后面操作影响前面排序顺序即高位重要性高于低位,
  171. 每个位层的排序为一个轮次,排序到最后就得到了有序
  172. 第一步找到最高位,求出轮次的次数
  173. 第二步开出一个备用空间用来存每个轮次的结果
  174. 第三步开出十个桶进行位层排序,将这些数进行重要性分级
  175. 第四步求前缀和,画出分区,将不同重要级区分开来
  176. 第五步将桶中的数存进备用空间
  177. 第六步更新数组
  178. 第七步重复三四五六步得到有序数列
  179. */
  180. void countSort(vector<int>& arr, int exp) {
  181. int n = arr.size();
  182. vector<int> output(n);
  183. vector<int> count(10, 0);
  184. for (int i = 0; i < n; i++) {
  185. count[(arr[i] / exp) % 10]++;
  186. }
  187. for (int i = 1; i < 10; i++) {
  188. count[i] += count[i - 1];
  189. }
  190. for (int i = n - 1; i >= 0; i--) {
  191. output[count[(arr[i] / exp) % 10] - 1] = arr[i];
  192. count[(arr[i] / exp) % 10]--;
  193. }
  194. for (int i = 0; i < n; i++) {
  195. arr[i] = output[i];
  196. }
  197. }
  198. void radixSort(vector<int>& arr) {
  199. int maxVal = *max_element(arr.begin(), arr.end());
  200. for (int exp = 1; maxVal / exp > 0; exp *= 10) {
  201. countSort(arr, exp);
  202. }
  203. }
  204. // 堆排序
  205. /*
  206. 第一步先构建堆结构(根的值最大,每个节点一定是他那个子树的最大值,但不和同层的有什么关系)
  207. 第二步将根(最大值)与最后一个元素交换,使得保证最后的节点是最大值
  208. 第三步将被交换的元素放回堆里,使得剩余元素再次构成堆结构,保证根是最大值
  209. 第四步 循环二三步,使得从最后到开始是从大到小,即得到开始到结束是从小到大
  210. */
  211. void heapify(vector<int>& arr, int n, int i) {
  212. int largest = i;
  213. int l = 2 * i + 1;
  214. int r = 2 * i + 2;
  215. if (l < n && arr[l] > arr[largest]) {
  216. largest = l;
  217. }
  218. if (r < n && arr[r] > arr[largest]) {
  219. largest = r;
  220. }
  221. if (largest != i) {
  222. swap(arr[i], arr[largest]);
  223. heapify(arr, n, largest);
  224. }
  225. }
  226. void treeSelectionSort(vector<int>& arr) {
  227. int n = arr.size();
  228. for (int i = n / 2 - 1; i >= 0; i--) {
  229. heapify(arr, n, i);
  230. }
  231. for (int i = n - 1; i > 0; i--) {
  232. swap(arr[0], arr[i]);
  233. heapify(arr, i, 0);
  234. }
  235. }
  236. // 选择排序
  237. /*
  238. 思路:每次都是找到最小的数,放在最前面
  239. */
  240. void selectionSort(vector<int>& arr) {
  241. int n = arr.size();
  242. for (int i = 0; i < n - 1; i++) {
  243. int minIndex = i;
  244. for (int j = i + 1; j < n; j++) {
  245. if (arr[j] < arr[minIndex]) {
  246. minIndex = j;
  247. }
  248. }
  249. swap(arr[i], arr[minIndex]);
  250. }
  251. }
  252. int main() {
  253. int n = 100000;
  254. vector<int> arr;
  255. // 以当前时间作为随机数种子
  256. unsigned seed = chrono::system_clock::now().time_since_epoch().count();
  257. mt19937 gen(seed);
  258. uniform_int_distribution<int> dis(1, 1000000); // 生成 1 到 1000 之间的随机数
  259. for (int i = 0; i < n; i++) {
  260. arr.push_back(dis(gen));
  261. }
  262. // 插入排序
  263. vector<int> insertionArr = arr;
  264. auto start1 = chrono::high_resolution_clock::now();
  265. insertionSort(insertionArr);
  266. auto end1 = chrono::high_resolution_clock::now();
  267. auto duration1 = chrono::duration_cast<chrono::milliseconds>(end1 - start1);
  268. cout << "插入排序时间(毫秒): " << duration1.count() << endl;
  269. // 希尔排序
  270. vector<int> shellArr = arr;
  271. auto start2 = chrono::high_resolution_clock::now();
  272. shellSort(shellArr);
  273. auto end2 = chrono::high_resolution_clock::now();
  274. auto duration2 = chrono::duration_cast<chrono::milliseconds>(end2 - start2);
  275. cout << "希尔排序时间(毫秒): " << duration2.count() << endl;
  276. // 折半插入排序
  277. vector<int> binaryInsertionArr = arr;
  278. auto start3 = chrono::high_resolution_clock::now();
  279. binaryInsertionSort(binaryInsertionArr);
  280. auto end3 = chrono::high_resolution_clock::now();
  281. auto duration3 = chrono::duration_cast<chrono::milliseconds>(end3 - start3);
  282. cout << "折半插入排序时间(毫秒): " << duration3.count() << endl;
  283. // 冒泡排序
  284. vector<int> bubbleArr = arr;
  285. auto start4 = chrono::high_resolution_clock::now();
  286. bubbleSort(bubbleArr);
  287. auto end4 = chrono::high_resolution_clock::now();
  288. auto duration4 = chrono::duration_cast<chrono::milliseconds>(end4 - start4);
  289. cout << "冒泡排序时间(毫秒): " << duration4.count() << endl;
  290. // 归并排序
  291. vector<int> mergeArr = arr;
  292. auto start5 = chrono::high_resolution_clock::now();
  293. mergeSort(mergeArr, 0, n - 1);
  294. auto end5 = chrono::high_resolution_clock::now();
  295. auto duration5 = chrono::duration_cast<chrono::milliseconds>(end5 - start5);
  296. cout << "归并排序时间(毫秒): " << duration5.count() << endl;
  297. // 快速排序
  298. vector<int> quickArr = arr;
  299. auto start6 = chrono::high_resolution_clock::now();
  300. quickSort(quickArr, 0, n - 1);
  301. auto end6 = chrono::high_resolution_clock::now();
  302. auto duration6 = chrono::duration_cast<chrono::milliseconds>(end6 - start6);
  303. cout << "快速排序时间(毫秒): " << duration6.count() << endl;
  304. // 基数排序
  305. vector<int> radixArr = arr;
  306. auto start7 = chrono::high_resolution_clock::now();
  307. radixSort(radixArr);
  308. auto end7 = chrono::high_resolution_clock::now();
  309. auto duration7 = chrono::duration_cast<chrono::milliseconds>(end7 - start7);
  310. cout << "基数排序时间(毫秒): " << duration7.count() << endl;
  311. // 树形选择排序
  312. vector<int> treeSelectionArr = arr;
  313. auto start8 = chrono::high_resolution_clock::now();
  314. treeSelectionSort(treeSelectionArr);
  315. auto end8 = chrono::high_resolution_clock::now();
  316. auto duration8 = chrono::duration_cast<chrono::milliseconds>(end8 - start8);
  317. cout << "树形选择排序时间(毫秒): " << duration8.count() << endl;
  318. // 选择排序
  319. vector<int> selectionArr = arr;
  320. auto start9 = chrono::high_resolution_clock::now();
  321. selectionSort(selectionArr);
  322. auto end9 = chrono::high_resolution_clock::now();
  323. auto duration9 = chrono::duration_cast<chrono::milliseconds>(end9 - start9);
  324. cout << "选择排序时间(毫秒): " << duration9.count() << endl;
  325. return 0;
  326. }

参考博客
链接:https://blog.csdn.net/weixin_52828997/article/details/128568924

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/824375
推荐阅读
相关标签
  

闽ICP备14008679号