您的位置:首页 > 编程语言 > Java开发

堆排序原理(图)及java版代码

2016-09-15 15:42 218 查看
数据结构中的堆可看做完全二叉树结构,其特性是任意一父节点的值分别大于或小于其左右子节点的值(大根堆和小根堆)

完全二叉树一般采用数组结构来表示,根据完全二叉树特性任意一父节点的值都大于(或小于)其子节点的值可知其第一个节点的值为树中的最大(最小)值,则每次将第一个父节点的值放到数组最后则可以实现排序。

首先来看一个图例:



点击查看大图

图中详细描述了如何将一组数构建成一个完全二叉树以及通过二叉树来排序,图里已写的很清楚了,这里就不赘述了。

下面来看java版实现:

**
* Created by white
* USER : WHITE .
* DATE : 2016/9/13 0013 下午 9:21.
* HeapSortUtil.java:堆排序工具类
*/
public class HeapSortUtil {

/**
* 构造完全二叉树
*
* @param array
*/
private void buildHeap(int[] array) {
int lastParentIndex = getLastParentIndex(array.length);
/*********************************************
* 从最后一个父节点开始将树中最大值换到父节点上
*********************************************/
for (int i = lastParentIndex; i >= 0; i--) {
buildTree(array, array.length, i);
}
}

/**
* 排序传入的父节点树及改动过的子树
*
* @param array
* @param parentIndex
*/
private void buildTree(int[] array, int maxIndex, int parentIndex) {
int leftChildIndex = getLeftChildIndex(parentIndex);
int rightChildIndex = getRightChildIndex(parentIndex);

/***************************************************************
* 左右节点最大值大于父节点则与父节点交换值并刷新交换后的子节点树
**************************************************************/
int maxValueIndex = parentIndex;
if (leftChildIndex < maxIndex &&
array[maxValueIndex] < array[leftChildIndex]) {
maxValueIndex = leftChildIndex;
}
if (rightChildIndex < maxIndex &&
array[maxValueIndex] < array[rightChildIndex]) {
maxValueIndex = rightChildIndex;
}

if (maxValueIndex != parentIndex) {
swapVaule(array, maxValueIndex, parentIndex);
buildTree(array, maxIndex, maxValueIndex);
}
}

/**
* 取堆的第一个节点和最后一个节点对换并重排剩下的树
*
* @param array
*/
private void sortHeap(int[] array) {
for (int i = array.length - 1; i > 0; i--) {
swapVaule(array, 0, i);
buildTree(array, i, 0);
}
}

/**
* 取堆的最后一个父节点
*
* @param arryLength 数组长度
* @return 返回树的最后一个父节点坐标
*/
private int getLastParentIndex(int arryLength) {
return (arryLength >> 1) - 1;
}

/**
* 获取左子节点的下标
*
* @param parentIndex
* @return
*/
private int getLeftChildIndex(int parentIndex) {
return (parentIndex << 1) + 1;
}

/**
* 获取右子节点的下标
*
* @param parentIndex
* @return
*/
private int getRightChildIndex(int parentIndex) {
return (parentIndex << 1) + 2;
}

/**
* 交换数组中元素
*
* @param array
* @param sourceIndex
* @param targetIndex
*/
private void swapVaule(int[] array, int sourceIndex, int targetIndex) {
int temp = array[sourceIndex];
array[sourceIndex] = array[targetIndex];
array[targetIndex] = temp;
}
}


通过以下方法调用:

public static void main(String[] args) {
HeapSortUtil util = new HeapSortUtil();
int[] array = new int[]{54, 21, 32, 85, 65, 45, 12, 20, 35, 96};
//构造完全二叉树
util.buildHeap(array);
//排序
util.sortHeap(array);
for (int i : array) {
System.out.print(i + ", ");
}
}


输出结果:

12, 20, 21, 32, 35, 45, 54, 65, 85, 96,


从结果看出已实现了堆排序,另代码里都有详细的注释,这里就不多解释了,有不明白的地方欢迎留言指出。

我的博客:blog.scarlettbai.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息