堆及堆排序java版

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]);
        }
    }
}

感謝閱讀,若有什麼問題,恭請各位大佬指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章