归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子 序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序 表,称为二路归并。
排序原理:
1、尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是 1为止。
2、将相邻的两个子组进行合并成一个有序的大组。
3、将相邻的两个子组进行合并成一个有序的大组
-- 原理图:
-- 归并原理:
-- 实现归并原理:
第一步:定义三个指针:int i , p1 , p2 ,i指向辅助数组assist中的开始填充索引,p1指向左子组开始索引,p2指向右子组的开始索引。
int i = lo; // 定义一个指针,指向assist数组中开始填充的位置
int p1 = lo; // 定义一个指针,指向第一个数组的开始索引
int p2 = mid + 1; // 定义一个指针,指向第二个数组的开始索引
第二步:比较左右子组指针处的元素大小,哪个小就往辅助数组assist的i索引处填充。
// 比较左右两边的子组,哪个小哪个填充到assist数组中
while(p1 <= mid && p2 <= hi) {
if(less(a[p1],a[p2])) {
assist[i++] = a[p1++];
}else {
assist[i++] = a[p2++];
}
}
第三步:第三个完成后肯定会有一个子组没有完成填充,索引需要定义两个循环如下
// 需要把未填充完的元素继续填充到assist数组中,下面两个循环只会执行一个
while (p1 <= mid) {
assist[i++] = a[p1++];
}
while (p2 <= hi) {
assist[i++] = a[p2++];
}
第四步:将辅助数组的元素,拷贝到原始数组中
// 再把数据拷贝到a数组中对应的索引处
for(int index = lo;index <= hi;index++) {
a[index] = assist[index];
}
-- API设计:
-- 代码:
/**
* 归并排序
*/
public class Merge {
private static Comparable[] assist; // 归并所需的辅助数组
// 对数组a中的元素进行排序
public static void sort(Comparable[] a) {
assist = new Comparable[a.length];
int lo = 0;
int hi = a.length - 1;
sort(a,lo,hi);
}
// 对数组a中从lo到hi的元素进行排序
public static void sort(Comparable[] a,int lo,int hi) {
// 如果完成分组结束递归
if(hi <= lo) {
return;
}
// 取分组中间值
int mid = lo + (hi - lo) / 2;
// 对lo到mid之间的元素进行排序
sort(a,lo,mid);
// 对mid+1到hi之间的元素进行排序
sort(a,mid+1,hi);
// 进行归并
marge(a,lo,mid,hi);
}
private static void marge(Comparable[] a,int lo,int mid,int hi) {
int i = lo; // 定义一个指针,指向assist数组中开始填充的位置
int p1 = lo; // 定义一个指针,指向第一个数组的开始索引
int p2 = mid + 1; // 定义一个指针,指向第二个数组的开始索引
// 比较左右两边的子组,哪个小哪个填充到assist数组中
while(p1 <= mid && p2 <= hi) {
if(less(a[p1],a[p2])) {
assist[i++] = a[p1++];
}else {
assist[i++] = a[p2++];
}
}
// 需要把未填充完的元素继续填充到assist数组中,下面两个循环只会执行一个
while (p1 <= mid) {
assist[i++] = a[p1++];
}
while (p2 <= hi) {
assist[i++] = a[p2++];
}
// 再把数据拷贝到a数组中对应的索引处
for(int index = lo;index <= hi;index++) {
a[index] = assist[index];
}
}
//比较v元素是否小于w元素
private static boolean less(Comparable v, Comparable w) {
return v.compareTo(w) < 0;
}
}
-- 测试代码:
public class MargeTest {
public static void main(String[] args) throws Exception {
Integer[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
Merge.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
-- 运行效果图:
@ 以上内容属于个人笔记