java中归并排序算法的递归与迭代
2014-09-21 13:53
316 查看
归并排序(merge sort)算法的思想是(以数组为例)将一个要排序的数组分为两半,对这两半分别排序,再将它们归并为一个有序数组。这是一种采用分治法的算法,就是将一个问题分解成两个或更多个规模更小但却截然不同的问题,分别解决每个新问题,再将它们的解法组合起来解决原问题。综上所述,归并排序主要分为两个步骤:一是如何将要排序的数组进行划分;二是如何已经排好序的数组合并为原来的数组。下面是基于递归与迭代的归并排序算法的设计。
基于递归的merge sort
基本思路:将一个要排序的数组,按序号分成原数组的两半(为了合并的方便,要保证划分后的数组序号是连续的),对这两半分别排序,将排序后的两个数组合并为一个临时数组,最后将这个临时数组复制回原数组。(注:划分后的两个数组继续使用划分的方法进行划分,只到每个数组中只含一个元素为止)
算法实现:
基本思路:从数组的始端开始,将每一对单个元素归并为含有两个元素的子数组,然后回到数组的始端,将每一对含有两个元素的子数组归并为含有4个元素的子数组,以此类推。注:归并两个子数组需要一个额外的临时数组,尽管使用这额外的数组的空间是必需的,但可以通过一定的技巧节省递归中消耗在将元素从临时数组复制回原数组的大部分时间。
算法实现:
基于递归的merge sort
基本思路:将一个要排序的数组,按序号分成原数组的两半(为了合并的方便,要保证划分后的数组序号是连续的),对这两半分别排序,将排序后的两个数组合并为一个临时数组,最后将这个临时数组复制回原数组。(注:划分后的两个数组继续使用划分的方法进行划分,只到每个数组中只含一个元素为止)
算法实现:
/** * 这一步主要是为了隐藏临时数组 * @param Array * @param first * @param last */ public void mergeSort(T[] Array,int first,int last) { T[] tempArray=(T[])new Comparable<?>[Array.length]; mergeSort(Array,tempArray,first,last); } /** * 归并排序 * @param Array 原数组 * @param tempArray 临时数组 * @param first 要排序数组的起始序号 * @param last 要排序数组的结束序号 */ public void mergeSort(T[] Array,T[] tempArray,int first,int last) { if(first<last) { int mid=(first+last)/2; mergeSort(Array,tempArray,first,mid); mergeSort(Array,tempArray,mid+1,last); merge(Array,tempArray,first,mid,last); } } /** * 将已经排好序的数组通过临时数组合并成原来的数组 * @param Array 原数组 * @param tempArray 临时数组 * @param first 要排序数组的起始序号 * @param mid 将数组分割成两半的序号 * @param last 要排序数组的结束序号 */ public void merge(T[] Array,T[] tempArray,int first,int mid,int last) { int leftIndex=first; int rightIndex=mid+1; int i=first; while(leftIndex<=mid&&rightIndex<=last) { if(Array[leftIndex].compareTo(Array[rightIndex])<0) { tempArray[i]=Array[leftIndex]; leftIndex++; } else { tempArray[i]=Array[rightIndex]; rightIndex++; } i++; } // 将左半边剩余的数组复制到临时数组中 while(leftIndex<=mid) { tempArray[i++]=Array[leftIndex++]; } // 将右半边剩余的数组复制到临时数组中 while(rightIndex<=last) { tempArray[i++]=Array[rightIndex++]; } // 将临时数组复制回原数组 for(int j=first;j<=last;j++) { Array[j]=tempArray[j]; } }基于迭代的merge sort
基本思路:从数组的始端开始,将每一对单个元素归并为含有两个元素的子数组,然后回到数组的始端,将每一对含有两个元素的子数组归并为含有4个元素的子数组,以此类推。注:归并两个子数组需要一个额外的临时数组,尽管使用这额外的数组的空间是必需的,但可以通过一定的技巧节省递归中消耗在将元素从临时数组复制回原数组的大部分时间。
算法实现:
/** * 将Array中的子数组归并到tempArray中,不需要将tempArray复制到Array中,而是将tempArray的子数组归并到Array中 * @param Array * @param first * @param last */ public void mergetionSort(T[] Array,int first,int last) { T[] tempArray=(T[])new Comparable<?>[Array.length]; int step=1; while(step<last) { mergePass(Array,tempArray,step,first,last); for(int i=0;i<tempArray.length;i++) System.out.print(tempArray[i]+" "); System.out.println(); step*=2; mergePass(tempArray,Array,step,first,last); for(int i=0;i<Array.length;i++) System.out.print(Array[i]+" "); System.out.println(); step*=2; } } /** * 对Array表按子表步长为step, [0,step-1],[step,step*2-1],归并到MergeList中 * @param Array 原数组 * @param tempArray 临时数组 * @param step 步长从1开始,然后按2的倍数进行递增(即指子数组中的元素) */ public void mergePass(T[] Array,T[] tempArray,int step,int first,int last) { int index=first;//下一个待归并段开始指针 while(index<=last) { //剩余元素存在两个待归并长度的元素 if(index+2*step<=(last+1)) { merge2(Array,tempArray,index,index+step-1,index+step*2-1); index=index+2*step; //将指针进行迭代 } //剩余元素存在一个待归并长度的元素和一个小于其归并长度的元素 else if(index+step<=(last+1)) { merge2(Array,tempArray,index,index+step-1,last); index=last+1; } //存在一个小于其归并长度的元素 else while(index<=last) { tempArray[index]=Array[index]; index++; } } } /** * 将已经排好序的数组通过临时数组合并成原来的数组 * @param Array 原数组 * @param tempArray 临时数组 * @param first 要排序数组的起始序号 * @param mid 将数组分割成两半的序号 * @param last 要排序数组的结束序号 */ public void merge2(T[] Array,T[] tempArray,int first,int mid,int last) { int leftIndex=first; int rightIndex=mid+1; int i=first; while(leftIndex<=mid&&rightIndex<=last) { if(Array[leftIndex].compareTo(Array[rightIndex])<0) { tempArray[i]=Array[leftIndex]; leftIndex++; } else { tempArray[i]=Array[rightIndex]; rightIndex++; } i++; } // 将左半边剩余的数组复制到临时数组中 while(leftIndex<=mid) { tempArray[i++]=Array[leftIndex++]; } // 将右半边剩余的数组复制到临时数组中 while(rightIndex<=last) { tempArray[i++]=Array[rightIndex++]; } }
相关文章推荐
- Java学习 - 递归转迭代完成Fibonacci
- 常见Java面试题 :迭代(iteration)和递归(recursion)
- Java中的迭代和递归详解
- Java 迭代与递归
- Thinking in java-16 递归和迭代
- 用java实现的迭代和递归插入排序
- Java中的迭代与递归
- java计算参数目录大小的递归和迭代实现
- Java中的迭代与递归
- 常见Java面试题 :迭代(iteration)和递归(recursion)
- Java中递归和迭代的区别
- Java将递归改成迭代的通用方法
- java使用递归迭代实现流程图展示(仅供参考)
- Java中的迭代与递归
- 常见Java面试题 :迭代(iteration)和递归(recursion)
- Java基本功练习十一(递归与迭代【汉诺塔、文件大小的显示、递归的辅助方法、尾递归】)
- java实现二分查找(迭代与递归)
- Java常用算法——迭代 & 递归篇
- Java递归与迭代
- java计算参数目录大小的递归和迭代实现