归并排序及优化(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 的 ...
随机推荐
- java 集合类Array、List、Map区别和优缺点
Java集合类主要分为以下三类: 第一类:Array.Arrays 第二类:Collection :List.Set第三类:Map :HashMap.HashTable 一.Array , Array ...
- java执行多条SQL语句
一次执行多条SQL的技术要点如下: DatabaseMetaData接口是描述有关数据库的整体综合信息,由于DatabaseMetaData是接口,所以没有构造方法,故不能使用new来创建Databa ...
- 用eclipes写第一个HelloWorld
打开 eclipes 后,首先点击左上角新建按钮,新建一个项目,如图: 选择 Java Project 选项: 如果没有java Project这个选项的话,选择次一个的 project 也可以,在跳 ...
- windows 下安装或者卸载memcache
1.安装到系统服务中: 在doc中:执行此软件 memcached.exe -d install(如果提示错误,要找到cmd.exe用管理员身份打开) 2.卸载: 在doc中:执行此软件 memcac ...
- Excel 2010高级应用-饼图(四)
Excel 2010高级应用-饼图(四) 基本操作如下: 1.新建空白文档,并命名饼图 2.单击"插入",找到饼图样例图 3.选择其中一种饼图图例,单击并在空白文档上生成饼图图框 ...
- Excel 2010高级应用-柱形图(一)
今天,做项目低保真,是在excel中画图,这也是我第一次在excel中画图. 每次做过的东西或者学到的新东西,我必须要把他们记录下来,这样到时再次用到它们时可以很容易地找到. 下面介绍做柱形图的过程: ...
- WebService之CXF注解之三(Service接口实现类)
ITeacherServiceImpl.java: /** * @Title:ITeacherServiceImpl.java * @Package:com.you.service.impl * @D ...
- freemarker处理哈希表的内建函数
freemarker处理哈希表的内建函数 1.简易说明 (1)map取值 (2)key取值 2.实现示例 <html> <head> <meta http-equiv=& ...
- JavaScript获取当前值
JavaScript获取当前值 1.说明 获取select下拉框中的选中的值以及文本值 2.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD ...
- 使用AspNetPager控件分页
页面后台写法 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { BindData(); } } pro ...