堆
堆是一顆完全二叉樹
堆中節點不大于或者不小于其父節點
入堆:
直接放入堆內部數據結構的最后,通過shiftUp操作,
與其父節點進行比較,交換位置
出堆:
內部數據結構的第一個(最大或者最小元素)和最后一個元素交換
位置 移除最后一個元素并返回 然后對第一個元素進行shiftDown操作
與其左右子節點比較,找出子節點中最大或者最小的節點交換位置
heapify
對給定的集合構建成最大堆 通過從后往前遍歷(n / 2) -1 個節點, 即所有
非葉子節點,進行shiftDown操作。
for (int i = (n >>> 1) - 1; i >= 0; i --) {
shiftDown(data[i])
}
將第一個元素(最大)和最后一個元素進行交換 讓后對前n-1個元素中的第一個
進行shiftDown操作,依次循環,最后完成堆排序
package cn.school;
import java.util.Arrays;
public class Heap {
// "原先18現在22"
public static void main(String[] args) throws Exception {
Heap main = new Heap();
main.heapSort(new Integer[]{234, 14, 12, 34, 299, 111});
}
public <T extends Comparable<T>> void heapSort(T[] arr) {
//heapify 將傳入的數組變成最大堆 對所有非葉子節點進行shiftDown操作
//從最后一個節點到第一個非葉子節點
for (int i = (arr.length >>> 1) - 1; i >= 0; i--) {
shiftDown(i, arr, arr.length);
}
// swap(arr, 0, arr.length - 1);
// shiftDown(0, arr, arr.length - 1);
// swap(arr, 0, arr.length - 2);
// shiftDown(0, arr, arr.length - 2);
// 建成最大堆后,將第一個元素和最后一個元素進行交換 之后再對0 - n-1 元素中
// 的0索引進行shiftDown操作,依次往復,最終排好序
int lastIndex = arr.length - 1;
while (lastIndex > 0) {
swap(arr, 0, lastIndex);
shiftDown(0, arr, lastIndex);
lastIndex --;
}
System.out.println(Arrays.toString(arr));
}
private void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
private <T extends Comparable<T>> void shiftDown(int i, T[] arr, int size) {
//將左右子節點中最大的和自己進行交換
while (leftChild(i) < size) {
int j = leftChild(i);
if (j + 1 < size && arr[j + 1].compareTo(arr[j]) > 0) {
j++;
}
if (arr[i].compareTo(arr[j]) >= 0) {
break;
}
T tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i = j;
}
}
private int leftChild(int i) {
return i * 2 + 1;
}
private int rightChild(int i) {
return i * 2 + 2;
}
}