白话排序算法(归并排序,快速排序)

本文深入探讨了归并排序和快速排序两种高效的线性排序算法。归并排序采用分治策略,通过递归将序列分为两半,分别排序后再合并;快速排序则选取基准元素进行分区,递归排序各分区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序算法已经完成了两篇了<<选择,插入,冒泡>><<希尔排序>> 继续把常用的算法完成掉,下面我们来讨论下关于归并排序,快速排序,这两种高级排序算法。这两种算法是线性的也即对于O(nlogn)的排序算法。

归并排序:

归并排序是在线性表中就学过的排序算法,归并排序用的是分治(Divide and Conquer)的思想(分治也是一个很不错的算法)。首先我们把给出的数列平分为左右两段,然后对两段数列分别进行排序,最后用刚才的合并算法把这两段(已经排过序的)数列合并为一个数列。

下面我们来看一些例子:

La = (3,5,8,11)

Lb = (2,6,8,9,11,15,20)

Lc=(2,3,5,6,8,8,9,11,11,15,20)

上面的La和Lb已经是有序序列了,由于两个数列已经有序了,我们会发现输出Lc数列的第一个数肯定为La的第一个数或者Lb的第一个数.

第一个输出Lb的2,然后再输出La的3

形成这样的数列

La=(5,8,11)

Lb=(6,8,9,11,15,20)

然后再循环上面的操作,就可以排序了。也就是进行递归的操作。

下面看下算法实现:

Code:
  1. voidMerge(int*a,intlen1,intlen2)
  2. {
  3. int*a1=newint[len1+1],*a2=newint[len2+1],len=len1+len2;
  4. for(inti=0;i<len1;i++)
  5. a1[i]=a[i];
  6. {
  7. }
  8. for(inti=0;i<len2;i++)
  9. {
  10. a2[i]=a[len1+i];
  11. }
  12. a1[len1]=a2[len2]=INT_MAX;
  13. for(inti=0,j=0,k=0;k<len;k++)
  14. {
  15. if(a1[i]<a2[j])
  16. {
  17. a[k]=a1[i++];
  18. }
  19. else
  20. {
  21. a[k]=a2[j++];
  22. }
  23. }
  24. delete[]a1;delete[]a2;
  25. }

快速排序:

快速排序是对冒泡法一种改进,它也运用了递归,它的排序思想是:我们想要把给定序列分成两段,并对这两段分别进行排序。一种不错的想法是,选取一个数作为“关键字”,并把其它数分割为两部分,把所有小于关键字的数都放在关键字的左边,大于关键字的都放在右边,然后递归地对左边和右边进行排序。把该区间内的所有数依次与关键字比较,我们就可以在线性的时间里完成分割的操作。完成分割操作有很多有技巧性的实现方法,比如最常用的一种是定义两个指针,一个从前往后找找到比关键字大的,一个从后往前找到比关键字小的,然后两个指针对应的元素交换位置并继续移动指针重复刚才的过程。这只是大致的方法,具体的实现还有很多细节问题。

当然如果想更完美点还要对基准关键字左右的分治区间进行划分算法。

下面是算法的大致思路过程:

初始状态:【49,38,65,97,76,13,27,49

一次划分后:【27,38,13】 49【76,97,65,49

分别进行快速排序:【13】 27 【38】 【49,65】76【97】

有序序列 【13,27,38,49,49,65,76,97】

算法代码(php实现):

Code:
  1. #include<stdio.h>
  2. voidQuickSort(int*b,intleftLimit,intrightLimit)
  3. {
  4. intleft=leftLimit;
  5. intright=rightLimit;
  6. intpivot_point=(int)((left+right)/2);//取出关键字
  7. do
  8. {
  9. //依次取出最大值
  10. while(b[left]<b[pivot_point]&&(left<rightLimit))
  11. {
  12. left++;
  13. }
  14. while(b[right]>b[pivot_point]&&(right>leftLimit))
  15. {
  16. right--;
  17. }
  18. if(left<=right)//把最大值交换到最后
  19. {
  20. inttemp=b[left];
  21. b[left]=b[right];
  22. b[right]=temp;
  23. left++;//再进行递加左值和递减右值
  24. right--;
  25. }
  26. }
  27. while(left<=right);
  28. if(leftLimit<right)
  29. {
  30. QuickSort(b,leftLimit,right);
  31. }
  32. if(rightLimit>left)
  33. {
  34. QuickSort(b,left,rightLimit);
  35. }
  36. }
  37. intmain(void)
  38. {
  39. inta[10];
  40. while(true)
  41. {
  42. for(intn=0;n<10;n++)
  43. {
  44. printf("/n第%d数:",(n+1));
  45. scanf("%d",&a[n]);
  46. }
  47. QuickSort(a,0,9);
  48. for(inti=0;i<10;i++)//输出排序后的数
  49. {
  50. printf("%d",a[i]);
  51. }
  52. }
  53. }

最后看个有趣的快速排序和冒泡排序的视频:点击播放



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值