Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)
春蚕到死丝方尽,蜡炬成灰泪始干
——无题
这里介绍两个比较难的算法:
1、堆排序
2、分治并归排序
先说堆。
这里请大家先自行了解完全二叉树的数据结构。
堆是完全二叉树。大顶堆是在堆中,任意双亲值都大于(或等于)其孩子值,就称其为大顶堆。
堆排序的步骤:
1、把数组想象成一个堆。数组的index+1就是其对应在堆中的序号
2、调堆中各值的顺序,得到大顶堆
3、将堆首位值与堆末尾值交换,最大值排序完毕
4、将堆得大小减1,重复步骤2和步骤3,直到堆中只剩下一个元素。排序完毕
上代码:
public class HeapSort {
public static void heapSort(int[] arr){
//建立完全二叉树,从最后一个双亲开始调整双亲值,直到根,调整完毕后大顶堆建立完成
for (int i = arr.length >> ; i > ; i --) {
heapAdjust(arr, i, arr.length);//调用堆要从1到length才符合堆的定义
}
//堆顶和堆低交换,获取最大值,然后调整大顶堆
for (int i = arr.length - ; i > ; i--) {
arr[i] = arr[i]^arr[];
arr[] = arr[i]^arr[];
arr[i] = arr[i]^arr[];
heapAdjust(arr, , i);//因为堆计数要从1开始,所以size = endIndex + 1
}
}
//调整大顶堆.先找左子,然后和右子比,取值大的,在和双亲自己比,自己比儿子大,break,否则交换.注意:根要从1开始才能找到左子
public static void heapAdjust(int[] arr, int parents, int size){
int j;//孩子们的标记是j,索引全部-1
int i = parents;//双亲是i,索引全部-1
while (i << <= size) {
j = i << ;//左子
if (j + <= size) {//有右子
if (arr[j - ] < arr[j + -])
j ++;
}
if (arr[i - ] > arr[j - ])
break;
arr[i-] = arr[i-]^arr[j-];
arr[j-] = arr[i-]^arr[j-];
arr[i-] = arr[i-]^arr[j-];
i = j;//儿子变为父亲,这里不知道是左子还是右子,所以不能直接通过for循环的迭代步骤<<i调整i值,如果是右子的话就错了(右子<<1+1)
}
}
}
再说分治并归排序
这里先要了解什么是递归
public class MergingTest {
public static void main(String[] args) {
mSort(, );
}
private static void mSort(int left, int right) {
int m = (left + right)/;
if (left == right) {
System.out.println(left);
return;
}
mSort(left, m);
mSort(m+, right);
}
}
这几行代码是并归算法的核心。运行代码将输出0123456789,虽然看上去很简单,但是如果真能明白,说明你已经完全理解递归的思想了,写出并归算法也就不在话下了。
为什么会输出0123呢?

代码执行的走向:1→2→4→2→5→2→1→3→6→3→7→3→1→return
能领悟这个东西就好办了,上代码:
public class MergingSort {
public static void mergingSort(int[] arr) {
int[] temp = new int[arr.length];
//temp是相当于一张牌,通过left,m,right在逻辑上分成两个数组,进行分治排序,arr是原数组,对数组排序不传数组怎么行?!
mSort(arr, temp, , arr.length-);
}
private static void mSort(int[] arr, int[] temp, int left, int right) {
//这里的分组逻辑没有使用到temp和arr,而是把它们作为参数传入merge方法
int m = (left+right)/ ;
if (left == right) {
return;
}
mSort(arr, temp, left, m);
mSort(arr, temp, m+, right);
merge(arr,temp,left,m,right);
}
private static void merge(int[]arr, int[] temp, int left, int m, int right) {
//分治排序极其简单,已知两个有序数组,要把他们合并成一个有序数组,用什么方法都不用说,大家一想就知道了。
for (int c = ;c < arr.length;c++){
temp[c] = arr[c];
}
for (int p = ; p < temp.length; p++) {
System.out.println("temp["+p+"] = " + temp[p]);
}
int i = left;
int j = m + ;
int k = left;
while (i<=m && j<=right) {
//使用分支结构,把每摞牌最小的那个挑出来给arr
if (temp[i] < temp[j]) {
arr[k++] = temp[i++];
}
if (temp[j] < temp[i]) {
arr[k++] = temp[j++];
}
}
//使用分支结构,把剩下的那摞牌都塞给arr
if (i > m) {
while (j <= right) {
arr[k++] = temp[j++];
}
}
if (j > right) {
while (i <= m) {
arr[k++] = temp[i++];
}
}
}
}
Java学习笔记——排序算法之进阶排序(堆排序与分治并归排序)的更多相关文章
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
- java学习笔记13--比较器(Comparable、Comparator)
java学习笔记13--比较器(Comparable.Comparator) 分类: JAVA 2013-05-20 23:20 3296人阅读 评论(0) 收藏 举报 Comparable接口的作用 ...
- java学习笔记11--集合总结
java学习笔记系列: java学习笔记10--泛型总结 java学习笔记9--内部类总结 java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Ob ...
- 20145330第八周《Java学习笔记》
20145330第八周<Java学习笔记> 第十五章 通用API 通用API 日志:日志对信息安全意义重大,审计.取证.入侵检验等都会用到日志信息 日志API Logger:注意无法使用构 ...
- 20145330第五周《Java学习笔记》
20145330第五周<Java学习笔记> 这一周又是紧张的一周. 语法与继承架构 Java中所有错误都会打包为对象可以尝试try.catch代表错误的对象后做一些处理. 使用try.ca ...
- java学习笔记04--数组
java学习笔记04--数组 数组复制的方法是使用System类提供的arraycopy()方法,其语法如下: System.arraycopy(Object src, int srcPos, Obj ...
- 20145230《java学习笔记》第七周学习总结
20145230 <Java程序设计>第7周学习总结 教材学习内容 Lambda语法概览 我们在许多地方都会有按字符串长度排序的需求,如果在同一个方法内,我们可以使用一个byName局部变 ...
- Java学习笔记之---方法和数组
Java学习笔记之---方法与数组 (一)方法 (1)什么是方法? 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 (2)方法的优点 使程序变得更简短而 ...
- java学习笔记之基础篇
java选择语句之switch //switch可以用于等值判断 switch (e) //int ,或则可以自动转化成int 的类型,(byte char short)枚举jdk 7中可以防止字 ...
随机推荐
- 【Egret】web版本报错:XMLHttpRequest cannot load
[Egret] web发行版本报错:XMLHttpRequest cannot load file:///C:/Users/PX/Documents/EgretProjects/Xt1/resourc ...
- poptest老李谈数据结构中深度优先和广度优先
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...
- 老李推荐:第6章6节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令队列
老李推荐:第6章6节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令队列 事件源在获得字串命令并把它翻译成对应的MonkeyEvent事件后,会把这些 ...
- BroadcastReceiver简单应用实例
BroadcastReceiver是android四大组件之一,主要用于接收广播,它的简单实现方法如下: 1.定义继承BroadcastReceiver的MyReceiver类: /** * Crea ...
- IC卡读卡器在安卓(android)下的开发
友我科技推出IC卡读卡器的Android开发包,软件工程师只需要导入jar类库文件,就可以在App中操作IC卡读卡器了. 目前IC卡读卡器的Android开发包开放操作的卡类型有:M1, S50, U ...
- iOS图片填充UIImageView(contentMode)
本文主要形象的介绍一下UIView的contentMode属性: 核心代码 [self.prp_imageView setContentMode:UIViewContentModeScaleAspec ...
- stick footer布局
需求: 将footer固定到底部.文章内容不足满屏时 footer在底部,超过满屏时footer在内容末尾. 方法一: <div id="wrap"> <div ...
- (一)一起学 Java Collections Framework 源码之 概述
. . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...
- win7下用SSH连接linux虚拟机
本文来自转载:原文 [需求] 在win7环境下用SSH(SecureShell)连接本地的一台虚拟机上ubuntu(11.10)系统 [环境] win7,ubuntu,vmware(8.0) [方案 ...
- JDBC的使用流程
//导入包: import java.sql.*; //注册JDBC驱动程序: Class.forName("com.mysql.jdbc.Driver"); //打开一个连接: ...