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中可以防止字 ...
随机推荐
- dev机上数据库中批量生成table
我的低效方法: 通过本地php脚本进行create: <?php //0-63 header("Content-type:text/html;charset=utf-8"); ...
- ElasticSearch查询 第五篇:布尔查询
布尔查询是最常用的组合查询,不仅将多个查询条件组合在一起,并且将查询的结果和结果的评分组合在一起.当查询条件是多个表达式的组合时,布尔查询非常有用,实际上,布尔查询把多个子查询组合(combine)成 ...
- Android kernel LOGO的更换方法
[从制作logo到LCD显示或者VGA显示logo] 1.制作logo的方法: 首先选择一个自己喜欢的图片,然后通过GIMP软件将该图片保存为.png格式, 变换方式这个就不说了(very easy) ...
- SVN将一台服务器上的代码迁移到另一台服务器上
由于我们出差,需要把svn服务器上的代码同步到我电脑上,自己各种百度折腾了快一天才弄好,下面来分享下我的具体思路和操作步骤.有2种方式:第一种方式:直接将本地自己dowm下来的代码导入到本地svn服务 ...
- Spring基础学习(五)—事务管理
一.事务基本认识 1.事务的概述 为了保证数据库中数据的一致性,数据的操作应当是离散的成组的逻辑单元.当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应当全部视 ...
- Activity的Task详解
1.Task Task是一个具有栈结构(后进先出)的容器,可以放置多个Activity实例.启动一个应用,系统就会为之创建一个Task,来放置根Activity.默认情况下,一个Activity启动另 ...
- 告别S! S! H!秒杀终端工具——FastLogin快捷登录
题记:自从接触到"跳板机"的概念后,一直就被烦不胜烦的机器名,ip地址,用户名,密码折腾的死去活来,心说能有个小精灵随时帮我输入那些重复的登录信息就好了.我见过最挫的方式就是用记事 ...
- Python爬虫 正则表达式
1.正则表达式概述 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来 ...
- Memetic Algorithm(文化基因算法)
1. 文化进化理论 威尔逊认为,从性质上来讲,文化进化总是以拉马克主义为特征的,即文化进化依赖于获得性状的传递,相对来说速度比较快:而基因进化是达尔文主义式的,依赖于经过几个世代的基因频率的改变,因而 ...
- Java中如何动态创建接口的实现
有很多应用场景,用到了接口动态实现,下面举几个典型的应用: 1.mybatis / jpa 等orm框架,可以在接口上加注解进行开发,不需要编写实现类,运行时动态产生实现. 2.dubbo等分布式服务 ...