树—堆
1、堆
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的
2、堆排序
具体的实现细节:
1). 构建一个最大堆。对于给定的包含有n个元素的数组A[n],构建一个最大堆(最大堆的特性是,某个节点的值最多和其父节点的值一样大。这样,堆中的最大元素存放在根节点中;并且,在以某一个节点为根的子树中,各节点的值都不大于该子树根节点的值)。从最底下的子树开始,调整这个堆结构,使其满足最大堆的特性。当为了满足最大堆特性时,堆结构发生变化,此时递归调整对应的子树。
2). 堆排序算法,每次取出该最大堆的根节点(因为根节点是最大的),同时,取最末尾的叶子节点来作为根节点,从此根节点开始调整堆,使其满足最大堆的特性。
3). 重复上一步操作,直到堆的大小由n个元素降到2个。
堆排序,大顶堆
public class HeapMaxSort {
/**
* 堆排序:堆排序不适宜于记录数较少的文件。
*/
public void heapSort(int[] array) {
if (array == null || array.length <=1)
return;
//1、建最大堆
buildMaxHeap(array);
//2、调整堆:堆顶与堆的最后一个元素交换位置。
for (int i = array.length - 1; i >= 1; i--) {
//交换堆顶和最后一个元素
swap(array, 0, i);
maxHeapAdjust(array,i,0);
}
}
// 根据输入数组构建一个最大堆
public void buildMaxHeap(int[] array) {
if (array == null || array.length <=1)
return;
int half = array.length / 2;
for (int i=half; i>=0; i--)
maxHeapAdjust(array, array.length, i);
}
//调整堆:堆顶与堆的最后一个元素交换位置。
private void maxHeapAdjust(int[] array, int heapSize, int index) {
// 左子节点索引
int left = index * 2 + 1;
// 右子节点索引
int right = index * 2 + 2;
// 最大节点索引
int largest = index;
// 如果左子节点大于父节点,则将左子节点作为最大节点
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
// 如果右子节点比最大节点还大,那么最大节点应该是右子节点
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
// 最后,如果最大节点和父节点不一致,则交换他们的值
if (index != largest) {
swap(array, index, largest);
// 交换完父节点和子节点的值,对换了值的子节点检查是否符合最大堆的特性
maxHeapAdjust(array, heapSize, largest);
}
}
//交换
private void swap(int[] data, int i, int j) {
int tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
}
/**
* 堆排序:堆排序不适宜于记录数较少的文件。
*/
public void heapSort(int[] array) {
if (array == null || array.length <=1)
return;
//1、建最大堆
buildMaxHeap(array);
//2、调整堆:堆顶与堆的最后一个元素交换位置。
for (int i = array.length - 1; i >= 1; i--) {
//交换堆顶和最后一个元素
swap(array, 0, i);
maxHeapAdjust(array,i,0);
}
}
// 根据输入数组构建一个最大堆
public void buildMaxHeap(int[] array) {
if (array == null || array.length <=1)
return;
int half = array.length / 2;
for (int i=half; i>=0; i--)
maxHeapAdjust(array, array.length, i);
}
//调整堆:堆顶与堆的最后一个元素交换位置。
private void maxHeapAdjust(int[] array, int heapSize, int index) {
// 左子节点索引
int left = index * 2 + 1;
// 右子节点索引
int right = index * 2 + 2;
// 最大节点索引
int largest = index;
// 如果左子节点大于父节点,则将左子节点作为最大节点
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
// 如果右子节点比最大节点还大,那么最大节点应该是右子节点
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
// 最后,如果最大节点和父节点不一致,则交换他们的值
if (index != largest) {
swap(array, index, largest);
// 交换完父节点和子节点的值,对换了值的子节点检查是否符合最大堆的特性
maxHeapAdjust(array, heapSize, largest);
}
}
//交换
private void swap(int[] data, int i, int j) {
int tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
}
每一章内容都是心血,希望大家不要抄袭~