当前位置:   article > 正文

数据结构与算法 排序_数据结构与算法排序

数据结构与算法排序

数据结构与算法 排序

一、简述

       记-排序方法。冒泡排序、选择排序、快速排序、直接插入排序。

        排序方法优劣比较:

       

       注:排序稳定性:如果待排序的表中存在多个关键字相同的元素,经过排序后这些相同关键字的元素的相对次序保持不变,则称这种排序方法是稳定的。反之有可能发生变化的则为不稳定。(例如按年龄排序,A与B的年龄相同,排序前A在B的前面,排序后A一定在B的前面,如此称为稳定。)

二、冒泡排序

       例如有N个数需要排序,第1趟比较N个数,相邻的两个数进行比较,较大值者后移(从小到大排序),一趟比较结束后,这一趟比较的数当中的最大值成为最后一个数;第2趟比较剩下的N-1个数,其中的最大值成为第N-1个数;以此类推,一共比较N-1趟。

       测试代码:

  1. #include <stdio.h>
  2. #define LENGTH 10 //元素个数
  3. void bubble_sort(int arr[], int len)
  4. {
  5. int i, j, tmp, print;
  6. for (i = 0; i < len; i++) /*变量i代表比较的趟数,每趟将未排序中的最大值放到最后*/
  7. {
  8. for (j = 0; j < len-1-i; j++) /*变量j代表每趟两两比较的次数*/
  9. {
  10. if (arr[j] > arr[j+1]) /*比较相邻的两值,大者后移*/
  11. {
  12. tmp = arr[j]; /*利用中间变量实现两个值互换*/
  13. arr[j] = arr[j+1];
  14. arr[j+1] = tmp;
  15. }
  16. }
  17. printf("第%d趟比较后:", i);
  18. for (print = 0; print < LENGTH; print++)
  19. {
  20. printf("%d ", arr[print]); /*将排序后的顺序输出*/
  21. }
  22. printf("\n");
  23. }
  24. }
  25. int main()
  26. {
  27. int i, arr[10]; /*定义变量及数组*/
  28. printf("请输入10个数:\n");
  29. for (i = 0; i < 10; i++)
  30. {
  31. scanf("%d", &arr[i]); /*从键盘中输入10个数*/
  32. }
  33. bubble_sort(arr, LENGTH);
  34. printf("排序后的顺序是:\n");
  35. for (i = 0; i < 10; i++)
  36. {
  37. printf("%d ", arr[i]); /*将排序后的顺序输出*/
  38. }
  39. printf("\n");
  40. return 0;
  41. }

       运行结果:

        

改进:有时候比较了前几次就排好序了(某一趟比较中没有发生交换,即没有反序,说明已经是顺序的),就不用继续比较,以节约资源。

测试代码:

  1. #include <stdio.h>
  2. #define LENGTH 10 //元素个数
  3. void bubble_sort(int arr[], int len)
  4. {
  5. int i, j, tmp, print,is_exchange;
  6. for (i = 0; i < len; i++) /*变量i代表比较的趟数,每趟将未排序中的最大值放到最后*/
  7. {
  8. is_exchange = 0;
  9. for (j = 0; j < len-1-i; j++) /*变量j代表每趟两两比较的次数*/
  10. {
  11. if (arr[j] > arr[j+1]) /*比较相邻的两值,大者后移*/
  12. {
  13. tmp = arr[j]; /*利用中间变量实现两个值互换*/
  14. arr[j] = arr[j+1];
  15. arr[j+1] = tmp;
  16. is_exchange = 1; //标志为发生交换
  17. }
  18. }
  19. printf("第%d趟比较后:", i);
  20. for (print = 0; print < LENGTH; print++)
  21. {
  22. printf("%d ", arr[print]); /*将排序后的顺序输出*/
  23. }
  24. printf("\n");
  25. if(is_exchange == 0)//没有发生交换,说明已经是排好序的
  26. {
  27. return;
  28. }
  29. }
  30. }
  31. int main()
  32. {
  33. int i, arr[10]; /*定义变量及数组*/
  34. printf("请输入10个数:\n");
  35. for (i = 0; i < 10; i++)
  36. {
  37. scanf("%d", &arr[i]); /*从键盘中输入10个数*/
  38. }
  39. bubble_sort(arr, LENGTH);
  40. printf("排序后的顺序是:\n");
  41. for (i = 0; i < 10; i++)
  42. {
  43. printf("%d ", arr[i]); /*将排序后的顺序输出*/
  44. }
  45. printf("\n");
  46. return 0;
  47. }

运行结果:

三、直接选择排序

       例如有N个数,第1趟从待排序的N数当中选出最小值最为第1个数,第2趟从剩下未排序的N-1个数中选出最小值最为第2个数,以此类推,直到全部将N个数排序。

                                        

                                                        

       测试代码:

  1. #include <stdio.h>
  2. #define LENGTH 10 //定义数组元素个数
  3. void select_sort(int arr[], int len)//选择排序
  4. {
  5. int i, j, k, tmp, print;
  6. for (i = 0; i < len-1; i++) /*变量i代表比较的趟数,每趟将未排序中的最小值放到前面*/
  7. {
  8. k = i;//k用来记住每趟中最小值元素的数组索引,比较完一趟再进行交换
  9. for (j = i+1; j < len; j++) /*变量j代表每趟两两比较的次数*/
  10. {
  11. if (arr[j] < arr[k]) /*大者后移*/
  12. {
  13. k = j;
  14. }
  15. }
  16. if (k != i) /*将无序区的最小值放到有序区*/
  17. {
  18. tmp = arr[i]; /*利用中间变量实现两个值互换*/
  19. arr[i] = arr[k];
  20. arr[k] = tmp;
  21. }
  22. printf("第%d趟比较后:", i);
  23. for (print = 0; print < LENGTH; print++)
  24. {
  25. printf("%d ", arr[print]); /*将排序后的顺序输出*/
  26. }
  27. printf("\n");
  28. }
  29. }
  30. int main()
  31. {
  32. int i, arr[LENGTH];
  33. printf("请输入%d个数:\n", LENGTH);
  34. for (i = 0; i < LENGTH; i++)
  35. {
  36. scanf("%d", &arr[i]); /*从键盘中输入LENGTH个数*/
  37. }
  38. select_sort(arr, LENGTH);
  39. printf("排序后的顺序是:\n");
  40. for (i = 0; i < LENGTH; i++)
  41. {
  42. printf("%d ", arr[i]); /*将排序后的顺序输出*/
  43. }
  44. printf("\n");
  45. return 0;
  46. }

       运行结果:

       

四、快速排序

       快速排序是由冒泡排序改进而来的。

       一趟快速排序的划分过程是采用从两头向中间扫描,同时交换与基准元素逆序的元素。具体做法是:设两个标识i和j,它们初始化分别指向无序区中的第一个元素和最后一个元素。假设无序区中的元素为arr[begin],arr[begin+1],...,arr[end]。则i的初始值为begin,j的初始值为end;首先将arr[begin]的值赋给中间变量tmp作为基准,然后令j自end起向左(向begin方向)扫描,直至arr[j]<tmp,然后将arr[j]的值赋给arr[i]。然后令i自i+1向右(向end方向)扫描,直至arr[i]>tmp,然后将arr[i]的值赋给arr[j]。然后令j自j-1向右..;然后令i自i+1向右。。。这样重复操作直到i==j,此时arr[begin],arr[begin+1],...,arr[i-1]这些关键字都小于tmp,而所有的.arr[i+1],...,arr[end]的关键字都大于tmp,此时可以将tmp中的元素赋给arr[i]。

                                        

      测试代码

  1. #include <stdio.h>
  2. static int index = 0;
  3. void Print(int arr[],int len)
  4. {
  5. int i;
  6. for(i=0;i<len;++i)
  7. {
  8. printf("%d ",arr[i]);
  9. }
  10. printf("\n");
  11. }
  12. void quick_sort(int arr[],int begin,int end)//将arr[begin]...arr[end]进行快速排序
  13. {
  14. int i = begin,j = end;
  15. int tmp;
  16. if(begin<end)
  17. {
  18. tmp = arr[begin];//取arr[begin]作为基准
  19. while(i!=j)//从两端向中间扫描,直至i==j
  20. {
  21. while(j>i && arr[j] >= tmp)//从右向左扫描,找到第一个小于tmp的arr[j]
  22. {
  23. --j;
  24. }
  25. arr[i] = arr[j];//找到第一个小于tmp的arr[j],将arr[j]赋给arr[i]
  26. while(i<j && arr[i] <= tmp)//从左向右扫描,找到第一个大于tmp的arr[i]
  27. {
  28. ++i;
  29. }
  30. arr[j] = arr[i];//找到第一个大于tmp的arr[i],将arr[i]赋给arr[j]
  31. }
  32. arr[i] = tmp;//arr[i]归位
  33. printf("第%d趟:", index++);
  34. Print(arr, 10);//打印当前排序后的元素
  35. quick_sort(arr,begin,i-1);//对左区间进行递归快速排序
  36. quick_sort(arr,i+1,end);//对右区间进行递归快速排序
  37. }
  38. }
  39. int main(int argc,char* argv[])
  40. {
  41. int arr[] = {6, 8, 7, 9, 0, 1, 3, 2, 4, 5};
  42. printf("before sort:");
  43. Print(arr, sizeof(arr)/sizeof(arr[0]));
  44. quick_sort(arr,0,sizeof(arr)/sizeof(arr[0] - 1));
  45. printf("after sort:");
  46. Print(arr, sizeof(arr)/sizeof(arr[0]));
  47. return 0;
  48. }

运行结果:

五、直接插入排序 (稳定)

       基本思想:把n个待排序的元素看为有序区和无序区,开始时有序区中只包含1个元素,无序区中包含有n-1个元素,排序过程中每次从无序区中取出第一个元素,将它插入到有序区中的适当位置;直到将无序区的元素都取完,排序完成。

       图例:

       

   测试代码:

  1. #include <stdio.h>
  2. void print_arr(int arr[], int len)//打印数组arr,len为数组的个数
  3. {
  4. int i;
  5. printf("arr= ");
  6. for(i=0; i<len; i++)
  7. {
  8. printf("%-3d ", arr[i]);
  9. }
  10. printf("\n");
  11. }
  12. //直接插入排序,arr为待排序的数组,len为数组的长度
  13. void straight_insertion_sort(int arr[], int len)
  14. {
  15. //进行从小到大排序
  16. int i,j,save;
  17. for(i=1;i<len;i++)//第一个元素作为有序区第一个元素,从第二个元素开始,逐个插入有序区
  18. {
  19. if(arr[i]<arr[i-1])//当前要插入的元素比前面的元素要小,前面的元素往后移,腾挪出一个位置,放置当前要插入的数
  20. {
  21. save = arr[i];//因为要进行移位,会进行覆盖,所以事先保存待插入的元素值
  22. for(j=i-1;j>=0 && arr[j]>save;j--)//只要比 待插入的元素值 大,都要往后移位
  23. {
  24. arr[j+1] = arr[j];
  25. }
  26. arr[j+1] = save;//移位结束,腾出的位置就是 放置待排序的元素 的合适位置
  27. }
  28. //打印当前数组的元素
  29. printf("第%2d趟排序,", i);
  30. print_arr(arr, len);
  31. printf("\n");
  32. }
  33. }
  34. int main(int argc, char *argv[])
  35. {
  36. int arr[] = {118,76,98,57,67,105,43,22,35,82,1};//待排序的数组
  37. int len = sizeof(arr)/sizeof(arr[0]);//求数组元素个数
  38. printf("排序前: ");
  39. print_arr(arr, len);//打印数组
  40. printf("\n");
  41. straight_insertion_sort(arr, len);//进行直接插入排序
  42. return 0;
  43. }

   运行结果:

 

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

闽ICP备14008679号