归并排序思想:将一个数组分成两部分分别排序(使用递归),然后将结果合并起来,即将最后两个有序的数组归并成一个更大的有序数组。
时间复杂度O(n) = NlogN
归并排序最吸引人的性质是它能保证将任意长度为N的数组排序所需时间和NlogN成正比,而缺点便是它所需的额外空间和N成正比。
归并排序又分为自顶向下的排序方式和自底向上的排序方式:
自顶向下的排序方式是利用了分治的思想,将一个大问题分割成若干个等价的子问题进行求解;
自底向上的排序方式是先归并那些微型数组,然后再成对归并得到的子数组。
两种排序方式的代码如下:
/**
*
* @author seabear
*
*/
public class MergeSort {
private static Comparable[] b ;
public static boolean less(Comparable v,Comparable w)
{
return v.compareTo(w) < 0;
}
public static void merge(Comparable[] a,int lo,int mid,int hi)
{
int i = lo;
int j = mid + 1;
for(int k = lo; k < hi + 1; k++)
{
b[k] = a[k];
}
for(int k = lo; k < hi + 1; k++)
{
if(i > mid)
{
a[k] = b[j++];
}
else if (j > hi)
{
a[k] = b[i++];
}
else if(less(b[i],b[j]))
{
a[k] = b[i++];
}
else
{
a[k] = b[j++];
}
}
}
/**
* 自顶向下和自底向上
* @param a
*/
public static void sort(Comparable[] a)
{
b = new Comparable[a.length];
//自顶向下
//sort(a,0,a.length-1);
//自底向上
for(int i = 1; i < a.length; i = i + i)
{
for(int lo = 0; lo < a.length - i; lo += i + i)
{
merge(a, lo, lo + i - 1, Math.min(lo + i + i - 1, a.length - 1));
}
}
}
public static void sort(Comparable[] a,int lo,int hi)
{
if(hi <= lo)
{
return ;
}
int mid = lo + (hi - lo) / 2;
sort(a,lo,mid);
sort(a,mid + 1,hi);
merge(a,lo,mid,hi);
}
public static void show(Comparable[] a)
{
for(int i = 0; i < a.length; i++)
{
System.out.print(a[i] + " ");
}
System.out.println();
}
public static void main(String[] args)
{
Integer[] a = new Integer[10];
for(int i = 0; i < 10; i++)
{
a[i] = (int)(Math.random() * 10 + 1);
}
show(a);
sort(a);
show(a);
}
}