java版基础排序归并排

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

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

0 1 2 3 4 5 6 7 8 9 10
2 4 6 8 1 4 0 2 7 4 10

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

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

0 1 2 3 4 5
1 2 4 4 6 8

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

0 1 2 3 4 5 6 7 8 9 10
1 2 4 4 6 8 0 2 7 4 10

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

 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 q=new LinkedList();//声明一个临时队列先进先出
    	  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++;
    	  }
       }
看到这里大家应该已经会了基数排序,但是我其实一直都对那个递归划分有些不是很清楚。所以为了弄清楚究竟如何递归的,我加了上面的两个输出语句。最后得出如下结论:

java版基础排序归并排_第1张图片

上面二叉树中的结点数字代表下标范围,分叉中间的数字就是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×tamp=1463015893&ver=1&signature=ApxbrqJNHSesYNQ2UF1VYl3WwA0qgIacTPzCkimq1PGIb15WBWOxlrrkuiEiyzohBZcBbG8YWUPCHxPrmWu2M2urOMp-R70xOs7MSuIx5SXFo*jrFKEjT0jjr0tIxevtlBB8XQi8mqFHCiXUpvsDkEKTGahWOfSK1q5cyu3o=;

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

你可能感兴趣的:(编程语言)