package cn.exercise;
/**
* 归并排序 O(nlogn)
* @author yang
*
*/
public class MergeArray {
// 辅助数组
private int[] bridge;
/**
* 外部排序主入口函数
* @param int[] sorted 要进行排序的函数
*/
public void sort(int[] sorted) {
if(sorted == null) {
return;
}
bridge=new int[sorted.length];
segmentation(sorted,0,sorted.length-1);
bridge=null;
}
/**
* 分割函数
* @param int[] sorted 要排序的数组
* @param int left 要分割的最小坐标
* @param int right 要分割的最大坐标
*/
private void segmentation(int[] sorted,int left,int right) {
if(left < right) {
int center=(left+right)/2;
// 能分割就继续再分割,分割的每个部分都是我们不知道是否有序或无序的
// 对该次分割的左部分判断
segmentation(sorted,left,center);
// 对该次分割的右部分判断
segmentation(sorted,center+1,right);
// 判断完毕,不能分割了,就进行左右部分排序
mergeSort(sorted,left,center,right);
// 排序好以后复制
copy(sorted, left, right);
}
}
/**
* 排序函数
* @param int[] sorted 要进行排序的函数
* @param int left 左部分的最小坐标
* @param int center 左部分的最大坐标
* @param int right 右部分的最大坐标
*/
private void mergeSort(int[] sorted,int left,int center,int right) {
// 分割好的右边部分的最小坐标
int right_start=center+1;
// 存放在辅助数组部分的最小坐标应该是分割好的部分的最小坐标,既left
int bridge_pos=left;
// 在归并的过程中,分割好的两部分,每部分的最小的坐标是不能超过其部分的最大坐标的
while(left <= center && right_start <= right) {
// 归并进行比较的方式是:将左右两个部分的每个坐标上的数进行比较,
// 将比较以后较小的值放到辅助数组中,较大的数继续进行与另一部分的值比较,
// 直到另一部分有比它大的值出现
if(sorted[left] < sorted[right_start]) {
bridge[bridge_pos++]=sorted[left++];
}else {
bridge[bridge_pos++]=sorted[right_start++];
}
}
// 存在这两个循环因为是,总有一个部分的某个值一直大于另一个部分的所有值
// 上面循环结束后,该“某个值”就出现了,但不知道该值是左右那个部分的,
// 所以有如下循环,如果left>center了,就说明该“某个值”是右边部分的。
// 由于我们不知道该“某个值”是不是它所在部分的最后一个值,所以要进行循环将它和它后面的值
// 全部放入到辅助数组中
while(right_start <= right) {
bridge[bridge_pos++]=sorted[right_start++];
}
while(left <= center) {
bridge[bridge_pos++]=sorted[left++];
}
}
/**
* 复制回原数组
*/
private void copy(int[] sorted,int left,int right) {
while(left <= right) {
sorted[left]=bridge[left];
left++;
}
}
}
java 归并排序原理
猜你喜欢
转载自blog.csdn.net/qq_43209531/article/details/88750386
今日推荐
周排行