当前位置:   article > 正文

数据结构 常用八大排序算法及代码实现_将一个序列排序的算法数据结构

将一个序列排序的算法数据结构

一、排序的介绍

1. 排序的分类

按照排序过程中所依据的原则的不同可以分类为:

  ►插入排序:直接插入排序  希尔排序

  ►交换排序:冒泡排序  快速排序

  ►选择排序:简单选择排序  堆排序

  ►归并排序

  ►基数排序

2. 排序算法比较

排序方法

最好时间

平均时间

最坏时间

辅助存储

稳定性

备注

选择排序

O(n^2)

O(n^2)

 O(n^2)

   O(1)

不稳定

 

插入排序

O(n)

O(n^2)

 O(n^2)

   O(1)

稳定

 

冒泡排序

O(n)

O(n^2)

 O(n^2)

   O(1)

稳定

 

希尔排序

O(n^1.3)

O(nlogn)

 O(n^2)

   O(1)

不稳定

 

快速排序

O(nlogn)

O(nlogn)

 O(n^2)

   O(logn)

不稳定

 

堆排序

O(nlogn)

O(nlogn)

O(nlogn)

   O(1)

不稳定

 

归并排序

O(nlogn)

O(nlogn)

O(nlogn)

   O(n)

稳定

 

基数排序

O(kn)

O(kn)

O(kn)

   O(n)

稳定

 

从平均情况看:堆排序、归并排序、快速排序胜过希尔排序。

从最好情况看:冒泡排序和直接插入排序更胜一筹。

从最差情况看:堆排序和归并排序强过快速排序。

虽然直接插入排序和冒泡排序速度比较慢,但是当初始序列整体或局部有序是,这两种算法的效率比较高。当初始序列整体或局部有序时,快速排序算法效率会下降。当排序序列较小且不要求稳定性是,直接排序效率较好;要求稳定性时,冒泡排序法效率较好。

二、直接插入排序

方法:对于给定的一组记录,初始时假定第一个记录自成一个有序的序列,其余的记录为无序序列;接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有序序列为止。

  1. #include <stdio.h>
  2. void InsertSort(int array[], int len)
  3. {
  4. int i, j, temp;
  5. for(i = 1; i < len; i++)
  6. {
  7. temp = array[i];
  8. for(j = i - 1; j >= 0; j--)
  9. {
  10. if(temp < array[j])
  11. {
  12. array[j + 1] = array[j];
  13. }
  14. else
  15. {
  16. break;
  17. }
  18. }
  19. array[j + 1] = temp;
  20. }
  21. }
  22. int main()
  23. {
  24. int i = 0;
  25. int a[] = {8, 2, 5, 3, 6, 7, 1, 9, 0};
  26. int length = sizeof(a) / sizeof(a[0]);
  27. InsertSort(a, length);
  28. for(i = 0; i < length; i++)
  29. {
  30. printf("%d ", a[i]);
  31. }
  32. return 0;
  33. }

三、希尔排序

希尔排序也称为“缩小增量排序”,基本原理是:首先将待排序的元素分为多个子序列,使得每个子序的元素个数相对较少,对各个子序分别进行直接插入排序,待整个待排序序列“基本有序后”,再对所有元素进行一次直接插入排序。 

具体步骤如下:

         (1)选择一个步长序列t1, t2, ..., tk,满足ti > tj(i <j),tk = 1。

         (2)按步长序列个数k,对待排序序列进行k趟排序。

         (3)每趟排序,根据对应的步长ti,将待排序的序列分割成ti个子序列,分别对各个子序列进行直接插入排序。

  1. #include <stdio.h>
  2. void ShellSort(int array[], int len)
  3. {
  4. int i, j, temp, h;
  5. for(h = len / 2; h > 0; h = h / 2)
  6. {
  7. for(i = h; i < len; i++)
  8. {
  9. temp = array[i];
  10. for(j = i - h; j >= 0; j -= h)
  11. {
  12. if(temp < array[j])
  13. {
  14. array[j + h] = array[j];
  15. }
  16. else
  17. {
  18. break;
  19. }
  20. }
  21. array[j + h] = temp;
  22. }
  23. }
  24. }
  25. int main()
  26. {
  27. int i = 0;
  28. int a[] = {8, 2, 5, 3, 6, 7, 1, 9, 0};
  29. int length = sizeof(a) / sizeof(a[0]);
  30. ShellSort(a, length);
  31. for(i = 0; i < length; i++)
  32. {
  33. printf("%d ", a[i]);
  34. }
  35. return 0;
  36. }

四、 冒泡排序

  1. #include <stdio.h>
  2. void BubbleSort(int array[], int len)
  3. {
  4. int i, j;
  5. int temp;
  6. for (i = 0; i < len -1; ++i)
  7. {
  8. for (j = len - 1; j > i; --j)
  9. {
  10. if (array[j] < array[j - 1])
  11. {
  12. temp = array[j];
  13. array[j] = array[j - 1];
  14. array[j - 1] = temp;
  15. }
  16. }
  17. }
  18. }
  19. int main()
  20. {
  21. int i = 0;
  22. int a[] = {29, 18, 87, 56, 3, 27};
  23. int length = sizeof(a) / sizeof(a[0]);
  24. BubbleSort(a, length);
  25. for (i = 0; i < length; i++)
  26. {
  27. printf("%d ", a[i]);
  28. }
  29. printf("\n");
  30. return 0;
  31. }

五、快速排序(高效)

采用“分而治之”的思想,把大的拆分为小的,小的在拆分为更小的。

原理:对于一组给定的记录,通过一趟排序后,将原序列分为两部分,其中前部分的所有记录均比后部分的所有记录小,然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中的所有记录均为有序为止。

  1. #include <stdio.h>
  2. int a[30], n;
  3. void QuickSort(int left, int right)
  4. {
  5. int i, j, tmp, tmp1;
  6. i = left;
  7. j = right;
  8. if(left >= right)
  9. {
  10. return;
  11. }
  12. while(i < j)
  13. {
  14. while(a[j] >= a[left] && i < j) //left作为参考值
  15. {
  16. j--;
  17. }
  18. while(a[i] <= a[left] && i < j)
  19. {
  20. i++;
  21. }
  22. if(i < j)
  23. {
  24. tmp = a[i];
  25. a[i] = a[j];
  26. a[j] = tmp;
  27. }
  28. }
  29. tmp1 = a[i];
  30. a[i] = a[left];
  31. a[left] = tmp1;
  32. QuickSort(left, i - 1);
  33. QuickSort(i + 1, right);
  34. }
  35. int main()
  36. {
  37. int i;
  38. printf("Please input n:\n");
  39. scanf("%d", &n);
  40. printf("Please input number:\n");
  41. for(i = 1; i <= n; i++)
  42. {
  43. scanf("%d", &a[i]);
  44. }
  45. QuickSort(1, n);
  46. for(i = 1; i <= n; i++)
  47. {
  48. printf("%d ", a[i]);
  49. }
  50. return 0;
  51. }

 六、简单选择排序

对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将记录与第一个记录的位置进行交换;接着对不包括第一个记录以外的其他记录进行第二轮排序,得到最小的记录并与第二个记录进行位置交换;重复该过程,直到进行比较的记录只有一个为止。

  1. #include <stdio.h>
  2. void SelectSort(int *num, int n)
  3. {
  4. int i, j;
  5. int tmp = 0, min = 0;
  6. for(i = 0; i < n - 1; i++)
  7. {
  8. min = i;
  9. for(j = i + 1; j < n; j++)
  10. {
  11. if(num[j] < num[min])
  12. {
  13. min = j;
  14. }
  15. }
  16. if(min != i)
  17. {
  18. tmp = num[i];
  19. num[i] = num[min];
  20. num[min] = tmp;
  21. }
  22. }
  23. }
  24. int main()
  25. {
  26. int i, len;
  27. int num[] = {4, 8, 2, 4, 0, 9, 1, 3, 5};
  28. len = sizeof(num) / sizeof(num[0]);
  29. SelectSort(num, len);
  30. for(i = 0; i < len; i++)
  31. {
  32. printf("%d ", num[i]);
  33. }
  34. return 0;
  35. }

 七、堆排序

  1.    将序列构造成一棵完全二叉树 ;
  2.    把这棵普通的完全二叉树改造成堆,便可获取最小值 ;
  3.    输出最小值 ;
  4.    删除根结点,继续改造剩余树成堆,便可获取次小值 ;
  5.    输出次小值 ;
  6.    重复改造,输出次次小值、次次次小值,直至所有结点均输出,便得到一个排序 。

 

  1. #include <stdio.h>//适用于数据量大的时候(构建浪费时间)
  2. void AdjustMinHeap(int *array, int pos, int len)
  3. {
  4. int tmp, child;
  5. for(tmp = array[pos]; 2 * pos + 1 <= len; pos = child)
  6. {
  7. child = 2 * pos + 1;
  8. if(child < len && array[child] > array[child + 1])
  9. {
  10. child++;
  11. }
  12. if(array[child] < tmp)
  13. {
  14. array[pos] = array[child];
  15. }
  16. else
  17. {
  18. break;
  19. }
  20. }
  21. array[pos] = tmp;
  22. }
  23. void Swap(int *a, int *b)
  24. {
  25. int temp;
  26. temp = *a;
  27. *a = *b;
  28. *b = temp;
  29. }
  30. void HeapSort(int *array, int len)
  31. {
  32. int i;
  33. for(i = len/2 - 1; i >= 0; i--)
  34. {
  35. AdjustMinHeap(array, i, len - 1);
  36. }
  37. for(i = len - 1; i >= 0; i--)
  38. {
  39. Swap(&array[0], &array[i]);
  40. AdjustMinHeap(array, 0, i - 1);
  41. }
  42. }
  43. int main()
  44. {
  45. int i;
  46. int array[] = {0, 13, 14, 1, 18, 27};
  47. int length = sizeof(array) / sizeof(array[0]);
  48. HeapSort(array, length);
  49. for(i = 0; i < length; i++)
  50. {
  51. printf("%d ", array[i]);
  52. }
  53. return 0;
  54. }

 八、归并排序

利用递归与分治技术将数据序列划分为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列。

原理:对于给定的一组记录,首先将两个相邻的长度为1的子序列进行归并,得到n/2个长度为2或者1的有序子序列,在将其两两归并,反复执行此过程,直到得到一个有序的序列为止。

 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void Merge(int array[], int start, int middle, int end)
  4. {
  5. int i, j, k, n1, n2;
  6. n1 = middle - start + 1;
  7. n2 = end - middle;
  8. int *L = (int *)malloc(n1 * sizeof(int));
  9. int *R = (int *)malloc(n2 * sizeof(int));
  10. for (i = 0, k = start; i < n1; i++, k++)
  11. {
  12. L[i] = array[k];
  13. }
  14. for (i = 0, k = middle + 1; i < n2; i++, k++)
  15. {
  16. R[i] = array[k];
  17. }
  18. for (k = start, i = 0, j = 0; i < n1 && j < n2; k++)
  19. {
  20. if (L[i] < R[j])
  21. {
  22. array[k] = L[i];
  23. i++;
  24. }
  25. else
  26. {
  27. array[k] = R[j];
  28. j++;
  29. }
  30. }
  31. if (i < n1)
  32. {
  33. for (j = i; j < n1; j++, k++)
  34. {
  35. array[k] = L[j];
  36. }
  37. }
  38. if (j < n2)
  39. {
  40. for (i = j; i < n2; i++, k++)
  41. {
  42. array[k] = R[i];
  43. }
  44. }
  45. }
  46. void MergeSort(int array[], int start, int end)
  47. {
  48. int middle;
  49. int i;
  50. if (start < end)
  51. {
  52. middle = (start + end) / 2;
  53. MergeSort(array, start, middle);
  54. MergeSort(array, middle + 1, end);
  55. Merge(array, start, middle, end);
  56. }
  57. }
  58. int main()
  59. {
  60. int i = 0;
  61. int a[] = {49, 38, 65, 97, 76, 13, 27};
  62. int length = sizeof(a) / sizeof(a[0]);
  63. MergeSort(a, 0, length -1);
  64. for (i = 0 ; i < length; i++)
  65. {
  66. printf("%d ", a[i]);
  67. }
  68. printf("\n");
  69. return 0;
  70. }

九、基数排序

步骤:

(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)

(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中 

  1. #include <stdio.h>
  2. int Getmax(int *a, int n)
  3. {
  4. int i, max;
  5. max = a[0];
  6. for(i = 0; i < n; i++)
  7. {
  8. if(max < a[i])
  9. {
  10. max = a[i];
  11. }
  12. }
  13. return max;
  14. }
  15. int countsort(int *a,int n, int exp)
  16. {
  17. int output[n];
  18. int buckets[10] = {0};
  19. int i;
  20. for(i = 0; i < n; i++)
  21. {
  22. buckets[(a[i] / exp) % 10]++;
  23. }
  24. for(i = 1; i < n; i++)
  25. {
  26. buckets[i] += buckets[i - 1];
  27. }
  28. for(i = n - 1; i >= 0; i--)
  29. {
  30. output[buckets[(a[i] / exp) % 10] - 1] = a[i];
  31. buckets[(a[i] / exp) % 10]--;
  32. }
  33. for(i = 0; i < n; i++)
  34. {
  35. a[i] = output[i];
  36. }
  37. return 1;
  38. }
  39. int Radixsort(int *a, int n)
  40. {
  41. int exp;
  42. int max = Getmax(a, n);
  43. for(exp = 1; (max / exp) > 0; exp *= 10 )
  44. {
  45. countsort(a,n,exp);
  46. }
  47. return 1;
  48. }
  49. int main()
  50. {
  51. int i;
  52. int a[] = {278, 109, 63, 930, 589, 184, 505, 269, 8, 83};
  53. int len = sizeof(a) / sizeof(a[0]);
  54. Radixsort(a, len);
  55. for(i = 0; i < len; i++)
  56. {
  57. printf("%d ", a[i]);
  58. }
  59. return 0;
  60. }

 

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

闽ICP备14008679号