原始归并排序:
自顶向下:Rsort() 自底向下:sort()
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
public class MergeSort {
private int[] a;
private int[] aux;//辅助 auxiliary
public MergeSort(int[] b)
{
a = new int[b.length];
aux = new int[b.length];
for (int i = 0; i < a.length; ++i)
a[i] = b[i];
}
public MergeSort(int N)
{
a = new int[N];
aux = new int[N];
for (int i = 0; i < a.length; ++i)
a[i] = StdRandom.uniform(-15 * N,15 * N);
}
public void merge(int lo,int mid,int hi)
{
for (int k = lo; k <= hi; ++k)
aux[k] = a[k];
int i = lo,j = mid + 1;
for (int k = lo; k <= hi; ++k)
{
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (aux[i] > aux[j]) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
public void sort(int lo,int hi)
{
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
sort(lo,mid);
sort(mid + 1,hi);
merge(lo,mid,hi);
}
public void Rsort()
{
sort(0,a.length - 1);
}
public void sort()
{
for (int sz = 1; sz < a.length; sz += sz)
for (int lo = 0; lo < a.length - sz; lo += sz+sz)
merge(lo,lo + sz - 1,Math.min(a.length - 1,lo + sz + sz - 1));
}
public void display()
{
for (int i = 0; i < a.length; ++i)
StdOut.print(a[i] + " ");
StdOut.println();
}
}
因为我们操作合并的子数组是有序的,如果两个子数组是有序的且a[mid+1]>a[mid]那我们就不必对此部分数组进行归并了,于是我们添加isSorted()检测
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
public class MergeIsSort {
private int[] a;
private int[] aux;
public MergeIsSort(int N)
{
a = new int[N];
aux = new int[N];
for (int i = 0; i < N; ++i)
a[i] = StdRandom.uniform(-15 * N,15 * N);
}
public MergeIsSort(int[] b)
{
a = new int[b.length];
aux = new int[a.length];
for (int i = 0; i < a.length; ++i)
a[i] = b[i];
}
public boolean isSorted(int mid)
{
return a[mid + 1] >= a[mid];
}
public void merge(int lo,int mid,int hi)
{
if (isSorted(mid))
return;
for (int k = lo; k<= hi; ++k)
aux[k] = a[k];
int i = lo,j = mid + 1;
for (int k = lo; k <= hi; ++k)
{
if (i > mid)
a[k] = aux[j++];
else if (j > hi)
a[k] = aux[i++];
else if (aux[i] > aux[j])
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
public void sort(int lo,int hi)
{
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
sort(lo,mid);
sort(mid + 1,hi);
merge(lo,mid,hi);
}
public void Rsort()
{
sort(0,a.length - 1);
}
public void sort()
{
for (int sz = 1; sz < a.length; sz += sz)
for (int lo = 0; lo < a.length - sz; lo += sz + sz)
merge(lo,lo+sz-1,Math.min(a.length - 1,lo+sz+sz-1));
}
public void display()
{
for (int i = 0; i < a.length; ++i)
StdOut.print(a[i] + " ");
StdOut.println();
}
}
对于小数组,我们降低归并排序的缺点,可以采用其他排序方法:
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
public class MergeAndInsert {
private int[] a;
private int[] aux;
public MergeAndInsert(int N)
{
a = new int[N];
aux = new int[N];
for (int i = 0; i < N; ++i)
a[i] = StdRandom.uniform(-15 * N,15 * N);
}
public MergeAndInsert(int[] b)
{
a = new int[b.length];
aux = new int[a.length];
for (int i = 0; i < a.length; ++i)
a[i] = b[i];
}
public void merge(int lo,int mid,int hi)
{
for (int k = lo; k <= hi; ++k)
aux[k] = a[k];
int i = lo,j = mid + 1;
for (int k = lo; k <= hi; ++k)
{
if (i > mid)
a[k] = aux[j++];
else if (j > hi)
a[k] = aux[i++];
else if (aux[i] > aux[j])
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
public void sort(int lo,int hi)
{
if (hi <= lo) return;
if (hi - lo <= 5)
{
InsertSort(lo,hi);
return;
}
int mid = lo + (hi - lo) / 2;
sort(lo,mid);
sort(mid + 1,hi);
merge(lo,mid,hi);
}
public void Rsort()
{
sort(0,a.length - 1);
}
public void sort()
{
int N = a.length;
for (int sz = 1; sz < a.length; sz += sz)
for (int lo = 0; lo < a.length - sz; lo += sz + sz)
{
if (sz <= 5)
{
InsertSort(lo,Math.min(N -1, lo + sz + sz - 1));
}
else
merge(lo,lo+sz-1,Math.min(N - 1, lo + sz + sz - 1));
}
}
public void InsertSort(int lo,int hi)
{
for (int i = lo; i < hi; ++i)
{
int j = i + 1;
int temp = a[j];
while (j > lo && temp < a[j - 1])
{
a[j] = a[j - 1];
--j;
}
a[j] = temp;
}
}
public void display()
{
for (int i = 0; i < a.length; ++i)
StdOut.print(a[i] + " ");
StdOut.println();
}
}
合并以上行为,我们就得到了优化的归并排序。。。。。