归并排序 - 递归非递归实现java

1.归并排序思想:

以2路归并为例,一个有n个记录的序列可以看作n个长度为1的有序子序列,将其两两合并成n/2(向上取整)个长度为2或1的有序序列,当有奇数个记录时为1,重复归并,直到得到一个长度为n的有序序列。

2.归并排序的复杂度:

递归:时间复杂度O(nlongn),空间复杂度O(n+longn)

非递归:时间复杂度O(nlongn),空间复杂度O(n)

所以用到归并排序,还是优先考虑非递归吧。

 3.递归实现

 1     public void mergeSort1(int[] data){
 2         msort(data,0,data.length-1);
 3     }
 4
 5     public void msort(int[] data, int start, int end){
 6         if(start < end){
 7             int mid = (start + end) >>> 1;
 8             msort(data,start,mid);
 9             msort(data,mid+1,end); //当mid+1 == end时,子序列长度为1,退出msort,进入merge()排序
10             merge(data,start,mid,end);
11         }
12     }
13
14     public void merge(int[] data, int start, int mid, int end){
15         int s1 = start;     //子序列1在data[]的起始下标
16         int s2 = mid + 1;  //子序列2在data[]的起始下标
17         int[] tmp = new int[end - start +1];
18         int index = 0; //临时数组tmp的下标
19         while((s1 <= mid) && (s2 <= end)){ //两个序列都还没有完全放入tmp[]中
20             if(data[s1] < data[s2]) tmp[index++] = data[s1++];
21             else tmp[index++] = data[s2++];
22         }
23         while(s1 <= mid){ //第2个序列已经完全放入tmp中,由于s1本身是有序的,将s1剩下的元素直接放入
24             tmp[index++] = data[s1++];
25         }
26         while(s2 <= end){
27             tmp[index++] = data[s2++];
28         }
29         for(int i = 0; i < tmp.length; i++){
30             data[start++] = tmp[i];
31         }
32     }

4.非递归实现

 1    public void mergeSort2(int[] data){
 2         int k = 1;  //k是子序列的长度,二路归并每次处理两个子序列,所以k< data.length 3         while(k < data.length){
 4             merge(data,k);
 5             k *= 2;
 6         }
 7     }
 8
 9     public void merge(int[] data, int len){
10         int s1 = 0;
11         int e1 = s1+len-1;
12         int s2 = e1+1;
13         int e2 = s2+len-1 < data.length ? s2+len-1 : data.length-1;
14         int[] tmp = new int[data.length];
15         int index = 0;
16         while(s2 < data.length){  //第一种情况存在两个序列
17             while((s1 <= e1) && (s2 <= e2)){
18                 if(data[s1] < data[s2]) tmp[index++] = data[s1++];
19                 else tmp[index++] = data[s2++];
20             }
21             while(s1 <= e1){
22                 tmp[index++] = data[s1++];
23             }
24             while(s2 <= e2){
25                 tmp[index++] = data[s2++];
26             }
27             s1 = e2 + 1;  //处理下一组的两个子序列
28             e1 = s1 + len -1;
29             s2 = e1 + 1;
30             e2 = s2 + len - 1 < data.length ? s2 + len -1 : data.length -1;
31         }
32         while(s1 < data.length){ //第二种情况,只剩下一个子序列了
33             tmp[index++] = data[s1++];
34         }
35         for(int i = 0; i < data.length; i++){
36             data[i] = tmp[i];
37         }
38     }

原文地址:https://www.cnblogs.com/leechee9/p/11785562.html

时间: 2024-10-12 04:12:43

归并排序 - 递归非递归实现java的相关文章

快速排序 归并排序的非递归版本 备忘

首先,归并排序,分治,递归解决小的范围,再合并两个有序的小范围数组,便得到整个有序的数组. 这是很适合用递归来写的,至于非递归,便是从小到大,各个击破,从而使得整个数组有序.代码如下: void merge(vector<int> &A, int left, int mid, int right) { int i=left,j=mid+1; vector<int> tmp(right-left+1,0); int k=0; while(i<=mid&&

快速排序递归非递归队列堆栈实现

递归实现 #include<iostream> using namespace std; template <class T> void QuickSort(T A[],int left,int right) { if(left<right) { int i=left; int j=right+1; do { do i++;while(A[i]<A[left]); do j--;while(A[j]>A[left]); if(i<j) Swap(A[i],A

二叉树总结—建树和4种遍历方式(递归&amp;&amp;非递归)

今天总结一下二叉树,要考离散了,求不挂!二叉树最重要的就是 建立.4种遍历方式,简单应用,如何判断两颗二叉树是否相似 二叉树分为 :1.完全二叉树  2.满二叉树 结构性质: 1).满二叉树 高度为h ,节点数则为 2^h - 1,且叶子节点全在最下层,且叶子节点数为2^(n-1)个{n代表二叉树层数,也叫深度} 2).n个节点的 完全二叉树 深度为 int(log2n)(以2为底n的对数)+ 1: 3).非空二叉树 叶子节点个数==双分支节点数+1 4).非空二叉树 某节点编号 n  若有左孩

【算法拾遗】二分查找递归非递归实现

转载请注明出处:http://blog.csdn.net/ns_code/article/details/33747953 本篇博文没太多要说的,二分查找很简单,也是常见常考的查找算法,以下是递归非递归的实现. 非递归实现: /* 非递归实现,返回对应的序号 */ int BinarySearch(int *arr,int len,int key) { if(arr==NULL || len<1) return -1; int low = 0; int high = len-1; while(l

【Java】 归并排序的非递归实现

归并排序可以采用递归方法(见:归并排序),但递归方法会消耗深度位O(longn)的栈空间,使用归并排序时,应该尽量使用非递归方法.本文实现了java版的非递归归并排序. 更多:数据结构与算法合集 思路分析 递归排序的核心是merge(int[] arr, int start, int mid, int end)函数,讲[start~mid-1]和[mid~end]部分的数据合并,递归代码是使用递归得到mid,一步步分解数组. 非递归时,我们直接定义要合并的小数组长度从1开始,在较小的长度数组都合

Java实现二叉树的创建、递归/非递归遍历

近期复习数据结构中的二叉树的相关问题,在这里整理一下 这里包含: 1.二叉树的先序创建 2.二叉树的递归先序遍历 3.二叉树的非递归先序遍历 4.二叉树的递归中序遍历 5.二叉树的非递归中序遍历 6.二叉树的递归后序遍历 7.二叉树的非递归后序遍历 8.二叉树的层次遍历 这里感谢博客http://blog.csdn.net/skylinesky/article/details/6611442的指导 /**二叉树的结点定义*/ class Node<T>{ private T value; pr

快速排序的递归非递归实习java

package com.edu.hpu.sort.swap.quick; import java.util.Arrays; import java.util.LinkedList; import com.edu.hpu.sort.Sort; public class QuickSort extends Sort { @Override public int[] doSort(int[] arr) { return quickSort2(arr, 0, arr.length - 1); } @Su

高速排序 归并排序的非递归版本号 备忘

首先,归并排序,分治.递归解决小的范围.再合并两个有序的小范围数组,便得到整个有序的数组. 这是非常适合用递归来写的.至于非递归.便是从小到大.各个击破,从而使得整个数组有序.代码例如以下: void merge(vector<int> &A, int left, int mid, int right) { int i=left,j=mid+1; vector<int> tmp(right-left+1,0); int k=0; while(i<=mid&&a

【书上讲解】归并排序的非递归写法

描述 [题解] 让区间的长度L为1,2,4,...2^(n-1) 然后对每个位置i开始的长度为L的区间归并有序,用归并排序的方法就好,然后i跳转到i+L 复杂度仍然是log2(n)*n级别的,注意写的时候的一些细节. 比如一定要让最后L>=n的情况进行过一次,不然无法保证整个序列是有序的 [代码] /* 归并排序非递归写法 */ #include <cstdio> const int N = 1e5; int a[N+10],b[N+10]; int n; //把a这个数组在l1..r2