码迷,mamicode.com
首页 > 编程语言 > 详细

Java 实现堆排序

时间:2015-04-05 23:20:28      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:

 堆排序和合并排序一样,是一种时间复杂度为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步)

        技术分享

package com.ys.sort;

import java.util.Arrays;
/*
 * 利用《大话数据结构》第9涨堆排序进行修改
 * 注意java中数组从0开始,节点s对应左右孩子是2s,2s+1;
 * 在java中节点s表示为a[s-1],左右孩子应为a[2s],a[2s-1]
*没有用到递归 *
*/ public class HeapSort { public void heapSort(int[] array){ maxHeapAdjust(array); //构建成大顶锥 for(int i=array.length-1;i>0;i--){ swap(array,0,i); heapAdjust(array,1,i); //重新调整为大顶堆 } } public void maxHeapAdjust(int[] array){ for(int i=array.length/2;i>0;i--){//构建成大顶锥 heapAdjust(array,i,array.length); } } public void heapAdjust(int[] a,int s,int m){ int temp,i,largest; //largest中存关键字较大的记录下标 temp = a[s-1]; //表示第s个节点 for(i=2*s;i<=m;i*=2){ if(i<m && a[i-1]<a[i]){ largest = i; ++i; }else largest = i-1; if(temp>=a[largest]) break; a[s-1] = a[largest]; s = largest+1; } a[s-1] = temp; } public void swap(int[] array,int from,int to){ int temp; temp = array[from]; array[from] = array[to]; array[to] = temp; } public static void main(String[] args) { HeapSort h = new HeapSort(); int[] a= {16, 14, 10, 8, 7, 9, 3, 2, 4, 1}; h.heapSort(a); String intArrayString = Arrays.toString(a); //将数组转换为字符串打印输出 System.out.print(intArrayString); } }

理论部分转自http://www.cnblogs.com/developerY/p/3319618.html

Java 实现堆排序

标签:

原文地址:http://www.cnblogs.com/hanhanzhu000/p/4394878.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!