归并排序及优化(Java实现)
普通归并排序
public class MergeSort {
/**
* @param arr 待排序的数组
* @param left 本次归并的左边界
* @param mid 本次归并的中间位置,也就是分界线
* @param right 本次归并的右边界
* @param <T> 泛型
* @local aux 辅助空间(Auxiliary Space)
*/
private static <T extends Comparable<? super T>> void merge(T[] arr, int left, int mid, int right) {
T[] aux = java.util.Arrays.copyOfRange(arr, left, right + 1);
//aux,i j分别是这两半的起始指针。将这两个闭区间归并[left ... mid] [mid + 1 ... right]
int i = left;
int j = mid + 1;
for (int t = left; t <= right; t++) {//把arr数组中的[left...right]区间都覆盖了,就完事了
if (i > mid) { //i == mid + 1 时越界(跃出左半数组)
arr[t] = aux[j++ - left];
} else if (j > right) {//j == right + 1 时越界(跃出右半数组)
arr[t] = aux[i++ - left];
} else if (aux[i - left].compareTo(aux[j - left]) < 0) {//如果i-left小,那么插入。(左半边数组的指针所指的数小)
arr[t] = aux[i++ - left];
} else { //如果j-left小,那么插入。(右半边数组的指针所指的数小)
arr[t] = aux[j++ - left];
}
}
}
private static <T extends Comparable<? super T>> void sort(T[] arr, int left, int right) {
if (left >= right) {
return;
}
int mid = (left + right) / 2;
sort(arr, left, mid);
sort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
private static void printArr(Object[] arr) {
for (Object o : arr) {
System.out.print(o);
System.out.print("\t");
}
System.out.println();
}
public static void main(String args[]) {
Integer[] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6};
printArr(arr);//3 5 1 7 2 9 8 0 4 6
sort(arr);
printArr(arr);//0 1 2 3 4 5 6 7 8 9
}
}
归并优化:利用插入排序
当递归到规模足够小时,利用插入排序
public class MergeSort {
/**
* @param arr 待排序的数组
* @param left 本次归并的左边界
* @param mid 本次归并的中间位置,也就是分界线
* @param right 本次归并的右边界
* @param <T> 泛型
* @local aux 辅助空间(Auxiliary Space)
*/
private static <T extends Comparable<? super T>> void merge(T[] arr, int left, int mid, int right) {
T[] aux = java.util.Arrays.copyOfRange(arr, left, right + 1);
//aux,i j分别是这两半的起始指针。将这两个闭区间归并[left ... mid] [mid + 1 ... right]
int i = left;
int j = mid + 1;
for (int t = left; t <= right; t++) {//把arr数组中的[left...right]区间都覆盖了,就完事了
if (i > mid) { //i == mid + 1 时越界(跃出左半数组)
arr[t] = aux[j++ - left];
} else if (j > right) {//j == right + 1 时越界(跃出右半数组)
arr[t] = aux[i++ - left];
} else if (aux[i - left].compareTo(aux[j - left]) < 0) {//如果i-left小,那么插入。(左半边数组的指针所指的数小)
arr[t] = aux[i++ - left];
} else { //如果j-left小,那么插入。(右半边数组的指针所指的数小)
arr[t] = aux[j++ - left];
}
}
}
/**
* @param arr 当规模小的时候对arr采用插入排序
* @param left 待排序部分的左边界
* @param right 待排序部分的右边界
* @param <T> 泛型
*/
private static <T extends Comparable<? super T>> void insertionSort(T[] arr, int left, int right) {
for (int i = left + 1; i <= right; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= 0 && temp.compareTo(arr[j]) < 0) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
private static <T extends Comparable<? super T>> void sort(T[] arr, int left, int right) {
if (right - left < 7) { //对小规模数据进行插入排序
insertionSort(arr, left, right);
return;
}
int mid = (left + right) / 2;
sort(arr, left, mid);
sort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
private static void printArr(Object[] arr) {
for (Object o : arr) {
System.out.print(o);
System.out.print("\t");
}
System.out.println();
}
public static void main(String args[]) {
Integer[] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6};
printArr(arr);//3 5 1 7 2 9 8 0 4 6
sort(arr);
printArr(arr);//0 1 2 3 4 5 6 7 8 9
}
}
归并排序继续优化:归并前判断一下是否还有必要归并
public class MergeSort {
/**
* @param arr 待排序的数组
* @param left 本次归并的左边界
* @param mid 本次归并的中间位置,也就是分界线
* @param right 本次归并的右边界
* @param <T> 泛型
* @local aux 辅助空间(Auxiliary Space)
*/
private static <T extends Comparable<? super T>> void merge(T[] arr, int left, int mid, int right) {
T[] aux = java.util.Arrays.copyOfRange(arr, left, right + 1);
//aux,i j分别是这两半的起始指针。将这两个闭区间归并[left ... mid] [mid + 1 ... right]
int i = left;
int j = mid + 1;
for (int t = left; t <= right; t++) {//把arr数组中的[left...right]区间都覆盖了,就完事了
if (i > mid) { //i == mid + 1 时越界(跃出左半数组)
arr[t] = aux[j++ - left];
} else if (j > right) {//j == right + 1 时越界(跃出右半数组)
arr[t] = aux[i++ - left];
} else if (aux[i - left].compareTo(aux[j - left]) < 0) {//如果i-left小,那么插入。(左半边数组的指针所指的数小)
arr[t] = aux[i++ - left];
} else { //如果j-left小,那么插入。(右半边数组的指针所指的数小)
arr[t] = aux[j++ - left];
}
}
}
/**
* @param arr 当规模小的时候对arr采用插入排序
* @param left 待排序部分的左边界
* @param right 待排序部分的右边界
* @param <T> 泛型
*/
private static <T extends Comparable<? super T>> void insertionSort(T[] arr, int left, int right) {
for (int i = left + 1; i <= right; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= 0 && temp.compareTo(arr[j]) < 0) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
private static <T extends Comparable<? super T>> void sort(T[] arr, int left, int right) {
// 先注释掉,为了测试
// if (right - left < 7) { //对小规模数据进行插入排序
// insertionSort(arr, left, right);
// return;
// }
if (left >= right) {
return;
}
int mid = (left + right) / 2;
sort(arr, left, mid);
sort(arr, mid + 1, right);
//在归并前判断一下,如果左边的最大的比右边的最小的还小(或者等于),那就不用归并了,已经有序了。
if (arr[mid].compareTo(arr[mid + 1]) <= 0) {
return;
}
merge(arr, left, mid, right);
}
public static <T extends Comparable<? super T>> void sort(T[] arr) {
sort(arr, 0, arr.length - 1);
}
private static void printArr(Object[] arr) {
for (Object o : arr) {
System.out.print(o);
System.out.print("\t");
}
System.out.println();
}
public static void main(String args[]) {
Integer[] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6};
printArr(arr);//3 5 1 7 2 9 8 0 4 6
sort(arr);
printArr(arr);//0 1 2 3 4 5 6 7 8 9
}
}
归并排序继续优化:只在排序前开辟一次空间
public class MergeSort {
public static <T extends Comparable<? super T>> void sort(T[] arr) {
T[] aux = (T[]) new Comparable[arr.length];
sort(arr, aux, 0, arr.length - 1);
}
private static <T extends Comparable<? super T>> void sort(T[] arr, T[] aux, int left, int right) {
if (right - left < 4) {
insertionSort(arr, left, right);
return;
}
// if (left >= right) {
// return;
// }
int mid = (left + right) / 2;
sort(arr, aux, left, mid);
sort(arr, aux, mid + 1, right);
if (arr[mid].compareTo(arr[mid + 1]) > 0) {
merge(arr, aux, left, mid, right);
}
}
private static <T extends Comparable<? super T>> void merge(T[] arr, T[] aux, int left, int mid, int right) {
System.arraycopy(arr, left, aux, left, right - left + 1);
int i = left;
int j = mid + 1;
for (int t = left; t <= right; t++) {
if (i > mid) {
arr[t] = aux[j++];
} else if (j > right) {
arr[t] = aux[i++];
} else if (aux[i].compareTo(aux[j]) < 0) {
arr[t] = aux[i++];
} else {
arr[t] = aux[j++];
}
}
}
private static <T extends Comparable<? super T>> void insertionSort(T[] arr, int left, int right) {
for (int i = left + 1; i <= right; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= left && temp.compareTo(arr[j]) < 0) {
arr[j + 1] = arr[j--];
}
arr[j + 1] = temp;
}
}
private static void printArr(Object[] arr) {
for (Object o : arr) {
System.out.print(o);
System.out.print("\t");
}
System.out.println();
}
public static void main(String args[]) {
Integer[] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6};
printArr(arr);//3 5 1 7 2 9 8 0 4 6
sort(arr);
printArr(arr);//0 1 2 3 4 5 6 7 8 9
}
}
归并排序及优化(Java实现)的更多相关文章
- 怎么优化JAVA程序的执行效率和性能?
现在java程序已经够快的了,不过有时写出了的程序效率就不怎么样,很多细节值得我们注意,比如使用StringBuffer或者StringBuilder来拼接或者操作字符串就比直接使用String效率高 ...
- Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法
Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法 java.lang.OutOfMemoryError: Java heap sp ...
- jvm系列(十):如何优化Java GC「译」
本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...
- jvm系列(七):如何优化Java GC「译」
本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的”Become a Java GC Expert”系列文章 ...
- jvm系列(十):如何优化Java GC「
转自:https://www.cnblogs.com/ityouknow/p/7653129.html 本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. ...
- 归并排序(非递归,Java实现)
归并排序(非递归):自底向上 public class MergeSort { /** * @param arr 待排序的数组 * @param left 本次归并的左边界 * @param mid ...
- MergeSort(归并排序)算法Java实现
归并排序 归并排序 (merge sort) 是一类与插入排序.交换排序.选择排序不同的另一种排序方法.归并的含义是将两个或两个以上的有序表合并成一个新的有序表.归并排序有多路归并排序.两路归并排序 ...
- 冒泡排序优化JAVA
本文对传统的冒泡排序进行了一些优化,减少了循环次数. 时间复杂度 若文件的初始状态是正序的,一趟扫描即可完成排序.所需的关键字比较次数 C 和记录移动次数 M 均达到最小值: C(min)=n-1 , ...
- 如何优化 Java 性能?
对于 Java 性能比较关心的同学大概都知道<Java Performance>这本书,一般而言,很多同学在日常写 Java Code 的时候很少去关心性能问题,但是在我们写 Code 的 ...
随机推荐
- 【开源】C#.NET股票历史数据采集,【附18年历史数据和源代码】
如果用知乎,可以关注专栏:.NET开源项目和PowerBI社区 重点重点:我没有买股票,没有买股票,股市是个坑,小心割韭菜哦. 本文的初衷是数据分析(分析结果就不说了,就是想看看筛选点数据),只不过搞 ...
- localhost直接访问子文件夹无法完成
刚装上新版的wamp,之前的改动都初始化了,发现了一个问题,localhost不能直接访问子文件夹了,从网上找了找答案,没费事,解决了. 将WWW目录下的index.php打开,更改里面的内容,更改内 ...
- FusionCharts 3D环饼图
1.设计静态页面 Doughnut.html: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"& ...
- vxWorks驱动架构
Vxworks内核驱动基本结构: 三张表:1. 系统设备表 2. 系统驱动表 3. 文件描述符表 Vxworks 内部对每个设备使用DEV_HDR 数据结构进行表示: Typedef str ...
- List转换成JSON对象报错(二)
List转换成JSON对象 1.具体报错如下 Exception in thread "main" java.lang.NoClassDefFoundError: org/apac ...
- Caused by: java.lang.ClassNotFoundException: javax.persistence.Entity
1.错误描述 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -nonaming ] { -help ...
- C# 带偏移量自定义分页方法
/// <summary> /// 带偏移量自定义分页方法 /// </summary> /// <param name="PageSize"> ...
- 芝麻HTTP:TensorFlow LSTM MNIST分类
本节来介绍一下使用 RNN 的 LSTM 来做 MNIST 分类的方法,RNN 相比 CNN 来说,速度可能会慢,但可以节省更多的内存空间. 初始化 首先我们可以先初始化一些变量,如学习率.节点单元数 ...
- hihocoder Challenge 29 A.序列的值
我现在就感觉我这人现在真的没有dp的意识 其实真写起来也不难,但是把就是练的少思维跟不上,dp从根本上就是一种状态的提炼和聚集. 按照题解的意思来,表示二进制第i位的值为j(0,1)的组合有多少,然后 ...
- WRT 版本说明
std_generic 标准通用版nokaid 是不带XBOX支持的(Kai代表连接游戏平台到网络上.)virtual** 表示支持虚拟专用网络的版本VOIP 带VOIP表示支持网络电话的版本.meg ...