import java.math.*;
public class Merge_sort {
/*
* 归并排序的
* 最坏运行时间是n*logn 当n趋近与无穷的时候,归并排序的速度远远高于插入排序
* 原因是归并排序是一种稳定的排序
方式,即归并排序不交换相同的元素,这就意味着,在按一种方式排序后同时可以按另外一种
方式进行排序
归并排序 (递归实现)
* 前提: 每个元素要有可比性,这里元素必须实现Comparable接口。
* 基本原理为:1.拆分 假设有N个元素的列表,首先把它拆分成2个或2个
* 以上的元素组成的新的列表(这里我的新列表长度不超过3),分别对对它们进行排序。
* 2.归并。把所有的排好序的子类表两两归并,如此重复,直到归并成一个含N个
* 元素的有序列表为止
* 图解:(大于3就继续分解)
* 大于3 8 7 6 5 4 3 2 1
* 分|解
* |
* 大于3 8 7 6 5 4 3 2 1
* 分|解 分|解
* | |
* 小于 3 8 7 6 5 4 3 2 1
* 排序 7 8 5 6 3 4 1 2
* 归并 | |
* 7 8 5 6 3 4 1 2
* | |
* 顺序保存 5 6 7 8 1 2 3 4
* |
* 归并 5 6 7 8 1 2 3 4
* |
* 顺序保存 1 2 3 4 5 6 7 8
* @param src 临时中间数组,它是目标数组的拷贝
* @param target 目标排序数组
* @param low 需排序的起始索引
* @param high 需排序的结束索引
* */
public static void main(String[] args) {
int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
sort(data, left, center);
// 对右边数组进行递归
sort(data, center + 1, right);
// 合并
merge(data, left, center, right);
print(data);
}
/**
* 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
*
* @param data
* 数组对象
* @param left
* 左数组的第一个元素的索引
* @param center
* 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
* @param right
* 右数组最后一个元素的索引
*/
public static void merge(int[] data, int left, int center, int right) {
// 临时数组
int[] tmpArr = new int[data.length];
// 右数组第一个元素索引
int mid = center + 1;
// third 记录临时数组的索引
int third = left;
// 缓存左数组第一个元素的索引
int tmp = left;
while (left <= center && mid <= right) {
// 从两个数组中取出最小的放入临时数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
// 将临时数组中的内容拷贝回原数组中
// (原left-right范围的内容被复制回原数组)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}
public class Merge_sort {
/*
* 归并排序的
* 最坏运行时间是n*logn 当n趋近与无穷的时候,归并排序的速度远远高于插入排序
* 原因是归并排序是一种稳定的排序
方式,即归并排序不交换相同的元素,这就意味着,在按一种方式排序后同时可以按另外一种
方式进行排序
归并排序 (递归实现)
* 前提: 每个元素要有可比性,这里元素必须实现Comparable接口。
* 基本原理为:1.拆分 假设有N个元素的列表,首先把它拆分成2个或2个
* 以上的元素组成的新的列表(这里我的新列表长度不超过3),分别对对它们进行排序。
* 2.归并。把所有的排好序的子类表两两归并,如此重复,直到归并成一个含N个
* 元素的有序列表为止
* 图解:(大于3就继续分解)
* 大于3 8 7 6 5 4 3 2 1
* 分|解
* |
* 大于3 8 7 6 5 4 3 2 1
* 分|解 分|解
* | |
* 小于 3 8 7 6 5 4 3 2 1
* 排序 7 8 5 6 3 4 1 2
* 归并 | |
* 7 8 5 6 3 4 1 2
* | |
* 顺序保存 5 6 7 8 1 2 3 4
* |
* 归并 5 6 7 8 1 2 3 4
* |
* 顺序保存 1 2 3 4 5 6 7 8
* @param src 临时中间数组,它是目标数组的拷贝
* @param target 目标排序数组
* @param low 需排序的起始索引
* @param high 需排序的结束索引
* */
public static void main(String[] args) {
int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
public static void mergeSort(int[] data) {
sort(data, 0, data.length - 1);
}
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
// 找出中间索引
int center = (left + right) / 2;
// 对左边数组进行递归
sort(data, left, center);
// 对右边数组进行递归
sort(data, center + 1, right);
// 合并
merge(data, left, center, right);
print(data);
}
/**
* 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
*
* @param data
* 数组对象
* @param left
* 左数组的第一个元素的索引
* @param center
* 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
* @param right
* 右数组最后一个元素的索引
*/
public static void merge(int[] data, int left, int center, int right) {
// 临时数组
int[] tmpArr = new int[data.length];
// 右数组第一个元素索引
int mid = center + 1;
// third 记录临时数组的索引
int third = left;
// 缓存左数组第一个元素的索引
int tmp = left;
while (left <= center && mid <= right) {
// 从两个数组中取出最小的放入临时数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
// 剩余部分依次放入临时数组(实际上两个while只会执行其中一个)
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
// 将临时数组中的内容拷贝回原数组中
// (原left-right范围的内容被复制回原数组)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
public static void print(int[] data) {
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + "\t");
}
System.out.println();
}
}