java版基础排序归并排

本文详细介绍了归并排序的原理及实现过程,通过实例演示了如何递归地将数组拆分和合并,最终达到排序的目的。文章还提供了完整的Java代码示例。

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

归并排和快排的时间复杂度都是o(nlogn).属于比较高效的一种排序算法。归并排序使用的分治思想。所谓的分治:分---就是将原数组划分派别,直到划到不可分为止;

治:将各个派别两两’治理‘,合成一个有序派别。需要强调的是这里的‘治’是指原先两个本就有序的派别重新比较治理。这里涉及的两个动作第一就是递归地划分,比较容易实现;另一个就是对两个有序的子数组进行比较合并,比较时我们可能需要一个临时存储区---一个先进先出的队列。当然你也可以申请一个与原始数组等长的临时数组。比较过程如下:从两个子数组开始处比较,谁小就把谁放入临时存储区,并取下一个值继续比较。如果一方比较完毕,则把另一方全部放入临时存储区中。最后再把临时存储区里的数组(已经全部有序)赋值回原始数组。临时比较图示说明如下:原始数组

012345678910
246814027410

注:第一行为下标,第二行为元素。目标从小到大排序。这里为了说明比较过程,我选取一个中间比较过程比如当我们把这些元素递归成单一派别,再合并时可能会出现下标为0-2的元素有序,下标为3-5的元素有序即是下面这种情况。

012345678910
246148027410
下面的合并就是将二者合并成整体有序。先将元素2和元素1比较,将较小元素1优先存入临时队列,同时将元素1的下标后移,开始下一次比较元素2和4比较;依次类推。如果哪一个元素移动到头。就把另一子数组中全部元素移入临时队列。合并后的临时队列为。注意:我这里强调凡是排好序的都是放在了临时队列中,原数组没做变动。这也是为什么最后我们要把临时数组再按序放回原数组中的原因。

012345
124468

放回原始数组中,也就是一次合并后原始数组可能出现的情况:

012345678910
124468027410

好了,基本逻辑就是这些.下面看一下代码:

 public static void main(String[] args){
    	   int a[]={2,4,6,8,1,4,0,2,7,4,10};
    	   merge_sort(a,0,a.length-1);
    	   ArrayUtils.printArray(a);//这里将排好后的结果输出,这个函数是写在另一个类中的静态输出函数。读者若嫌麻烦,不妨弄个for循环输出。
    	   }
       public static void merge_sort(int a[],int first,int end){
    	   if(first<end){    //这里划分一定要分成单个元素成派。理由很简单因为合并的基础是有序子数组。只有单个元素可以认为有序,多个则不然。
    		   int mid=(first+end)/2;  //采用中间划分
    		   //System.out.println(mid);//这里是我调试所用,不需要看
    		   merge_sort(a,first,mid);//这里是两条递归语句,就是划分派别。注意这里划分其实是划分的下标
    		   merge_sort(a,mid+1,end);
    		   merge(a,first,mid,end);//合并
    		 //  ArrayUtils.printArray(a);//调试所用,不用看
    		   
    	   }
       }
       public static void merge(int a[],int first,int mid,int end){
    	  Queue<Integer> q=new LinkedList<Integer>();//声明一个临时队列先进先出
    	  int indexA=first;//考虑一下为什么不直接使用first还需要再申请一个新的临时变量?答案在最后一句我们其实是在每合并一次就赋值回原数组一次。
    	  int indexB=mid+1;
    	  while(indexA<=mid&&indexB<=end){
    		  if(a[indexA]<=a[indexB]){  //谁小把谁优先加入临时队列
    			  q.offer(a[indexA]);
    			  indexA++;
    		  }
    		  else{
    			  q.offer(a[indexB]);
    			  indexB++;
    		  }	  
    	  }
    	  while(indexA<=mid){          //这个队列还没比较完,依次加入队列
    		  q.offer(a[indexA]);
    		  indexA++;
    	  }
    	  while(indexB<=end){
    		  q.offer(a[indexB]);
    		  indexB++;
    	  }
    	  int index=0;
    	  while(q.size()>0){     //赋值回原始数组
    		  a[first+index]=q.poll();
    		  index++;
    	  }
       }
看到这里大家应该已经会了基数排序,但是我其实一直都对那个递归划分有些不是很清楚。所以为了弄清楚究竟如何递归的,我加了上面的两个输出语句。最后得出如下结论:


上面二叉树中的结点数字代表下标范围,分叉中间的数字就是mid值。这个二叉树有点丑,如果大家有这方面的画图工具不妨推荐一下。如果取消我的那两条调试语句注释,并对main函数中的排序后输出注释掉。可以看到输出结果如下:

5
2
1
0
{2, 4, 6, 8, 1, 4, 0, 2, 7, 4, 10}
{2, 4, 6, 8, 1, 4, 0, 2, 7, 4, 10}
4
3
{2, 4, 6, 1, 8, 4, 0, 2, 7, 4, 10}
{2, 4, 6, 1, 4, 8, 0, 2, 7, 4, 10}
{1, 2, 4, 4, 6, 8, 0, 2, 7, 4, 10}
8
7
6
{1, 2, 4, 4, 6, 8, 0, 2, 7, 4, 10}
{1, 2, 4, 4, 6, 8, 0, 2, 7, 4, 10}
9
{1, 2, 4, 4, 6, 8, 0, 2, 7, 4, 10}
{1, 2, 4, 4, 6, 8, 0, 2, 4, 7, 10}
{0, 1, 2, 2, 4, 4, 4, 6, 7, 8, 10}
从上面可以看出Java顺序执行,1.先执行二叉树的左分支一直到左侧不能划分为止,然后向上比较合并。2.边合并边赋值回原数组。所以结果才会出现乱中有序的输出啊。好了
以上就是我的见解。如有不当之处,敬请留言指点。互相学习,共同提高。最后贴出两篇其他牛人写的,也是我参考过的连接。http://mp.weixin.qq.com/s?src=3&timestamp=1463015893&ver=1&signature=ApxbrqJNHSesYNQ2UF1VYl3WwA0qgIacTPzCkimq1PGIb15WBWOxlrrkuiEiyzohBZcBbG8YWUPCHxPrmWu2M2urOMp-Rvpn70xOs7MSuIx5SXFo*jrFKEjT0jjr0tIxevtlBB8XQi8mqFHCiXUpvsDkEKTGahWOfSK1q5cyu3o=;

还有一篇博客http://www.cnblogs.com/jillzhang/archive/2007/09/16/894936.html。再次声明,文章仅为学习交流之用。

Java归并排序是一种排序算法,它将数组切分为较小的部分,然后递归地对这些部分进行排序,并最后将它们合并起来。在Java中,归并排序是通过底层的Arrays.sort()方法实现的[1]。下面是Java归并排序的一般步骤和代码实现。 1. 定义一个mergeSort()方法,该方法接受一个数组a和两个整数lo和hi作为参数。这个方法用来进行递归调用,对数组的指定部分进行排序。 2. 在mergeSort()方法中,首先创建一个与数组大小相同的临时数组temp,用于存放排序后的元素。 3. 然后,调用另一个mergeSort()方法,该方法接受一个数组a和四个整数lo、hi、mid作为参数。这个方法用来进行归并操作,将数组的两个子数组合并成一个有序数组。 4. 在mergeSort()方法中,首先计算切分点mid,然后判断子数组的长度是否大于1,如果大于1则继续拆分子数组。 5. 接下来,递归地调用mergeSort()方法对两个子数组进行排序,分别传入参数a、temp、lo、mid和a、temp、mid+1、hi。 6. 最后,在mergeSort()方法中调用merge()方法将两个子数组合并成一个有序数组。 Java归并排序的核心是merge()方法,该方法将两个有序子数组合并成一个有序数组。 总结起来,Java归并排序通过递归地将数组划分为较小的部分,并合并这些部分以获得最终的排序结果。这种排序算法Java中被广泛应用,并且可以在源码中找到其实现。 参考文献: 麦田怪圈 (Crop Circle), 维基百科, https://zh.wikipedia.org/wiki/麥田怪圈 人为制作麦田怪圈的方法, 百度百科, https://baike.baidu.com/item/人为制作麦田怪圈的方法 归并排序, 维基百科, https://zh.wikipedia.org/wiki/归并排序<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [归并排序详解,Java描述。](https://blog.youkuaiyun.com/weixin_30539625/article/details/97734524)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值