前言

临近毕业,开始找工作,近期一直在看算法导论(CLRS)同时各种刷题。希望以后有时间把所有学习心得和刷题心得记录下来。

堆排序和合并排序一样,是一种时间复杂度为O(nlgn)的算法,同时和插入排序一样,是一种就地排序算法(不需要额外的存储空间)。堆排序需要用到一种被称为最大堆的数据结构,与java或者lisp的gc不一样,这里的堆是一种数据结构,他可以被视为一种完全二叉树,即树里面除了最后一层其他层都是填满的。也正是因为这样,树里面每个节点的子女和双亲节点的序号都可以根据当前节点的序号直接求出。

Parent(i)=i/2

Left(i)=2*i

Right(i)=2*i+1

如上图所示,1位置的子女节点分别为2,3  2节点的子女节点为4,5 2的双亲节点为1 考察其他节点也很容易发现上述关系。最大堆是一种特殊的堆,其特点是每个双亲节点的值都比子女节点大。他的这一特点使得他可以实现nlgn的就地排序。现在我们先来看看怎么构建和保持一个最大堆。

最大堆的构建和保持

我们现在有一个数组A,大小是n,假设其中元素按照完全二叉树的方式排列。如何将其构造成一个最大堆?首先我们知道最大堆的每个子树都符合最大堆的性质(根节点值大于所有子节点)。同时我们知道序号为(n/2+1)~n的元素都是叶子节点(因为其子女节点的序号都大于n,即说明没有子女节点),因此我们构建最大堆的操作就在序号为1~n/2的元素内进行(其他元素已满足最大堆性质)。我们定义如下操作maxify(i):将以i位置节点为根的子树改造成最大堆。其操作内容如下:对于每个节点i,我们考察他与子女节点的大小,如果他比某个子女节点小,则将他与子女节点中最大的那个互换位置,然后在相应的子女节点位置重复操作,直到到达堆的叶子节点或者考察的位置比子女节点的值都要大为止。由此可知我们构造最大堆buildmaxheap的过程就是在每个内部节点上调用maxify过程,依次到树的根部,此时其左右子树都是最大堆,现在在根节点调用maxify即完成了最大堆的构造。

堆排序的操作

有了最大堆的基础结构后,我们就可以利用最大堆的性质进行排序HeapSort,我们从根节点开始操作,因为根节点是这个数组中最大的元素,因此我们将其于数组中最后一个元素对换(排序后,最大元素应该在最后)将heapsize减1,然后再在根节点出调用maxify过程将新的堆重新最大堆化。依次循环,我们每次都能将现有堆中最大的元素放到堆末尾。最后就完成了整个排序过程。操作情况见下图(只列出了前4步)

代码及运行结果

public class MaxHeap {
int[] heap;
int heapsize;
public MaxHeap(int[] array)
{
this.heap=array;
this.heapsize=heap.length;
}
public void BuildMaxHeap()
{
for(int i=heapsize/2-1;i>=0;i--)
{
Maxify(i);//依次向上将当前子树最大堆化
}
}
public void HeapSort()
{
for(int i=0;i<heap.length;i++)
{
//执行n次,将每个当前最大的值放到堆末尾
int tmp=heap[0];
heap[0]=heap[heapsize-1];
heap[heapsize-1]=tmp;
heapsize--;
Maxify(0);
}
}
public void Maxify(int i)
{
int l=Left(i);
int r=Right(i);
int largest; if(l<heapsize&&heap[l]>heap[i])
largest=l;
else
largest=i;
if(r<heapsize&&heap[r]>heap[largest])
largest=r;
if(largest==i||largest>=heapsize)//如果largest等于i说明i是最大元素 largest超出heap范围说明不存在比i节点大的子女
return ;
int tmp=heap[i];//交换i与largest对应的元素位置,在largest位置递归调用maxify
heap[i]=heap[largest];
heap[largest]=tmp;
Maxify(largest);
}
public void IncreaseValue(int i,int val)
{
heap[i]=val;
if(i>=heapsize||i<=0||heap[i]>=val)
return;
int p=Parent(i);
if(heap[p]>=val)
return;
heap[i]=heap[p];
IncreaseValue(p, val);
} private int Parent(int i)
{
return (i-1)/2;
}
private int Left(int i)
{
return 2*(i+1)-1;
}
private int Right(int i)
{
return 2*(i+1);
}
}
public class Demo {
public static void main(String[] args)
{
int[] array=new int[]{1,2,3,4,7,8,9,10,14,16};
MaxHeap heap=new MaxHeap(array);
System.out.println("执行最大堆化前堆的结构:");
printHeapTree(heap.heap);
heap.BuildMaxHeap();
System.out.println("执行最大堆化后堆的结构:");
printHeapTree(heap.heap);
heap.HeapSort();
System.out.println("执行堆排序后数组的内容");
printHeap(heap.heap); }
private static void printHeapTree(int[] array)
{
for(int i=1;i<array.length;i=i*2)
{
for(int k=i-1;k<2*(i)-1&&k<array.length;k++)
{
System.out.print(array[k]+" ");
}
System.out.println();
}
}
private static void printHeap(int[] array)
{
for(int i=0;i<array.length;i++)
{
System.out.print(array[i]+" ");
}
} }

堆排序详解以及java实现的更多相关文章

  1. 事件驱动模型实例详解(Java篇)

    或许每个软件从业者都有从学习控制台应用程序到学习可视化编程的转变过程,控制台应用程序的优点在于可以方便的练习某个语言的语法和开发习惯(如.net和java),而可视化编程的学习又可以非常方便开发出各类 ...

  2. Heapsort 堆排序算法详解(Java实现)

    Heapsort (堆排序)是最经典的排序算法之一,在google或者百度中搜一下可以搜到很多非常详细的解析.同样好的排序算法还有quicksort(快速排序)和merge sort(归并排序),选择 ...

  3. Myeclipse Templates详解(一) —— Java模板基础

    目录 Templates简介 MyEclipse自带Templates详解 新建Template 自定义Template 因为自己比较懒,尤其是对敲重复代码比较厌恶,所以经常喜欢用快捷键和模板,Mye ...

  4. 二叉搜索树详解(Java实现)

    1.二叉搜索树定义 二叉搜索树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值: 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根 ...

  5. Java AtomicInteger类的使用方法详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 首先看两段代码,一段是Integer的,一段是AtomicInteger的,为以下: public class Samp ...

  6. java 流操作对文件的分割和合并的实例详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 java 流操作对文件的分割和合并的实例详解 学习文件的输入输出流,自己做一个小的示例,对文件进行分割和合并. 下面是代 ...

  7. springboot扫描自定义的servlet和filter代码详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 这几天使用spring boot编写公司一个应用,在编写了一个filter,用于指定编码的filter,如下: /** ...

  8. Java实现的二叉堆以及堆排序详解

    一.前言 二叉堆是一个特殊的堆,其本质是一棵完全二叉树,可用数组来存储数据,如果根节点在数组的下标位置为1,那么当前节点n的左子节点为2n,有子节点在数组中的下标位置为2n+1.二叉堆类型分为最大堆( ...

  9. 【知识详解】JAVA基础(秋招总结)

    JAVA基础 目录 JAVA基础 问:面向过程(POP)和面向对象(OOP)? 问:Python和Java的区别? 问:java的八大基本数据类型? 问:封装继承多态说一下? 问:方法和函数的区别? ...

随机推荐

  1. Delphi for iOS开发指南(4):在iOS应用程序中使用不同风格的Button组件

    http://blog.csdn.net/DelphiTeacher/article/details/8923481 在FireMonkey iOS应用程序中的按钮 FireMoneky定义了不同类型 ...

  2. mod_pagespeed

    https://github.com/pagespeed/mod_pagespeed.git https://developers.google.com/speed/pagespeed/module/ ...

  3. android RadioButton文字居中的方法

    每个RadioButton的style原先是这样的: <style name="radiobutton_style" > <item name="and ...

  4. 设计模式之单件模式(Singleton Pattern)

    一.单件模式是什么? 单件模式也被称为单例模式,它的作用说白了就是为了确保“该类的实例只有一个” 单件模式经常被用来管理资源敏感的对象,比如:数据库连接对象.注册表对象.线程池对象等等,这种对象如果同 ...

  5. IIS发布网站之后,页面图片和js未加载出错

    [IIS相关]mvc做的web发布之后,运行之后界面上的图片和js都没有加载出来.      解决方案:安装IIS的时候需要勾选ASP选项,否则会出现这种情况. 如果项目是用.Netframework ...

  6. 微软官方实例 RazorPagesMovie 在 asp.net core 2.1 版本下的实战

    微软官方实例 RazorPagesMovie 在 asp.net core 2.1 版本下的实战 友情提示: 操作系统: MacOS 10.13.5 dotnet core: version 2.1. ...

  7. BitAdminCore框架更新日志20180529

    索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxin/coo ...

  8. .net Framework使用之 MongoDB

    新建Helper using MongoDB.Bson; using MongoDB.Driver; using System; using System.Collections.Generic; u ...

  9. VUE.js 中取得后台原生HTML字符串 原样显示问题

    今天使用vue调试页面,发现了页面上的一个问题,后台数据传过来的HTML字符串并没有被转换为正常的HTML代码,一拍脑门,发现忘记转换了,于是满心欢喜加上了{{{}}}.但是之后构建发现报错: 为此去 ...

  10. 【cocos2d-x 3.0-Mac配置篇】

    就在昨天触控正式发布了3.0正式版本... 在这个喜大普奔的日子里,我们又开始了新一轮的革命,先不说其他的,再来看看3.0目录文件里面有什么? 首先是精简了很多,无论是从目录结构,和所用到的工具类,都 ...