1.什麼是完全二叉樹
(1)葉子結點在n層或者n-1層
(2)從最左端開始
2.堆(最大堆)
(1)完全二叉樹
(2)parent > childs
比如:
但是可能有些結構不滿足堆的特性,比如:4<10,我們就需要調整成堆。
heapify操作:以i位置結點爲parent去調整,使其滿足堆的特性
相應的代碼:
/**
* 堆:完全二叉樹(可以用數組存儲)
* parent > child
*
* 而且有: child1 = (parent * 2) + 1
* child2 = (parent * 2) + 2
*
* parent = (child - 1) / 2;
* tree :完全二叉樹
* n : 結點數量
* i :表示以i爲parent對堆進行調整,使其滿足堆的特性
* */
private static void heapify(int[] tree, int n, int i) {
if (tree == null || i >= n){
return;
}
// 找到parent和child中最大的結點下標
int max = i;
int child1 = i * 2 + 1;
int child2 = i * 2 + 2;
if (child1< n && tree[child1] > tree[max]){
max = child1;
}
if (child2 < n && tree[child2] > tree[max]){
max = child2;
}
// 說明確實需要調整,否則父結點就是最大的結點,就不用調整了
if (max != i){
swap(tree,i,max);
//然後在遞歸的對下面的堆進行調整
heapify(tree,n,max);
}
}
/**
* 交換
* */
private static void swap(int[] tree, int i, int j) {
int temp = tree[i];
tree[i] = tree[j];
tree[j] = temp;
}
要是這個tree一開始就無序呢?就咋咋都是無序的
我們就需要從最後一個parent結點開始依次向上開始調整使其變成堆(heapify操作)
/**
* 如果tree剛開始就無序,沒有符合堆的parent > child
* 那麼,我們就需要從最後一個葉子結點的parent開始向上調整
* 執行heapify操作
* */
private static void buildHeap(int[] tree, int n) {
//最後一個節點的下標
int lastNode = n - 1 ;
//找到其父親結點
int lastParent = (lastNode - 1) >> 1 ;
//依次調整
for (int i = lastParent; i >=0; i--) {
heapify(tree,n,i);
}
}
好了,現在我們已經是一個堆了
3. 堆排序
現在我們要求需要排序?要怎麼做呢?
/**
* 堆排序
* */
private static void heapSort(int[] tree,int n){
// 構建一個堆
buildHeap(tree,n);
for (int i = n - 1; i >=0; i--) {
//將第一個元素與最後一個元素交換(相當於把最大值換到數組末尾了)
swap(tree,i,0);
//調整第一個元素使其成爲最大堆
//注意現在堆大小變成i了,因爲你要將最大值移出去,tree長度在變化
heapify(tree,i,0);
}
}
至此我們的堆排序就完成了
全部代碼如下:
package com.dataConstruct;
/**
* Created by BorisLiu on 2019/10/25
*/
public class Heap {
/**
* 交換
* */
private static void swap(int[] tree, int i, int j) {
int temp = tree[i];
tree[i] = tree[j];
tree[j] = temp;
}
/**
* 堆:完全二叉樹(可以用數組存儲)
* parent > child
*
* 而且有: child1 = (parent * 2) + 1
* child2 = (parent * 2) + 2
*
* parent = (child - 1) / 2;
* tree :完全二叉樹
* n : 結點數量
* i :表示以i爲parent對堆進行調整,使其滿足堆的特性
* */
private static void heapify(int[] tree, int n, int i) {
if (tree == null || i >= n){
return;
}
// 找到parent和child中最大的結點下標
int max = i;
int child1 = i * 2 + 1;
int child2 = i * 2 + 2;
if (child1< n && tree[child1] > tree[max]){
max = child1;
}
if (child2 < n && tree[child2] > tree[max]){
max = child2;
}
// 說明確實需要調整,否則父結點就是最大的結點,就不用調整了
if (max != i){
swap(tree,i,max);
//然後在遞歸的對下面的堆進行調整
heapify(tree,n,max);
}
}
/**
* 如果tree剛開始就無序,沒有符合堆的parent > child
* 那麼,我們就需要從最後一個葉子結點的parent開始向上調整
* 執行heapify操作
* */
private static void buildHeap(int[] tree, int n) {
//最後一個節點的下標
int lastNode = n - 1 ;
//找到其父親結點
int lastParent = (lastNode - 1) >> 1 ;
//依次調整
for (int i = lastParent; i >=0; i--) {
heapify(tree,n,i);
}
}
/**
* 堆排序
* */
private static void heapSort(int[] tree,int n){
// 構建一個堆
buildHeap(tree,n);
for (int i = n - 1; i >=0; i--) {
//將第一個元素與最後一個元素交換(相當於把最大值換到數組末尾了)
swap(tree,i,0);
//調整第一個元素使其成爲最大堆
heapify(tree,i,0);
}
}
public static void main(String[] args) {
//int tree[] = {4,10,3,5,1,2};
int tree[] = {2,5,3,1,10,4};
int n = 6;
//heapify(tree,n,0);
// buildHeap(tree,n);
heapSort(tree,n);
for (int i = 0; i < n; i++) {
System.out.println(tree[i]);
}
}
}
感謝閱讀,若有什麼問題,恭請各位大佬指正