1468449529
讲真,我是因为数据结构考试看了一下复习资料才知道的堆排序,一学期没上课的后果。于是,查了资料了解了这一算法。
俗话说堆栈堆栈,堆跟栈是什么就不说了。堆可以被看成是一棵树,那么就有了二叉堆,最小堆最大堆的说法。以下是百度百科的对堆的简述
堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。
最大堆和最小堆是二叉堆的两种形式。
最大堆:根结点的键值是所有堆结点键值中最大者。
最小堆:根结点的键值是所有堆结点键值中最小者。
而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。
最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。
以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。
如图所示
堆的存储如下图所示
那么很容易看出第n个结点的父结点下标就为(n – 1) / 2。它的左右子结点下标分别为2 * n + 1 和 2 * n + 2。如第0个结点左右子结点下标分别为1和2。
代码实现
package com.w.sort;
public class Dsort {
static int[] array = new int[] { 15, 21, 6, 30, 23, 66, 20, 17 };
/**
* 生成最小堆,最小堆的任意子树根节点不大于任意子结点
*
* @param array
* @param heapSize
* 堆的大小
* @param parent
* 父节点下标索引
*/
static void minHeap(int[] array, int heapSize, int parent) {
int left = parent * 2 + 1; // 左孩子
int right = parent * 2 + 2;// 右孩子
if (left < heapSize && array[left] > array[parent]) { // 判断孩子是否大于父节点的值,大于则交换,并继续找当前节点的子节点进行判断
swap(array, left, parent);
minHeap(array, heapSize, left);
}
if (right < heapSize && array[right] > array[parent]) {// 同上
swap(array, right, parent);
minHeap(array, heapSize, right);
}
}
static void swap(int[] array, int x, int y) {
int t = array[x];
array[x] = array[y];
array[y] = t;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int length = array.length;
// 初始化为最小堆
for (int i = length / 2; i >= 0; i--)
minHeap(array, length - 1, i);
for (int i = length - 1; i >= 1; i--) {
swap(array, 0, i); // 每次将最小的数array[0]换到后面有序区间
minHeap(array, i, 0);
}
for (int i = 0; i < length; i++)
System.out.print(array[i] + " ");
}
}