java數據結構之順序二叉樹和堆

1. 順序存儲二叉樹

底層存儲數據的時候使用數組存儲,順序二叉樹性質:

1. 順序二叉樹通常只考慮完全二叉樹;

2. 第n個元素的左子節點爲 2*n +1 ;

3. 第n個元素的右子節點爲:2*n +2;

4. 第n個元素的父節點爲 (n-1)/2;

5. n 表示二叉樹中的第幾個元素(按0開始編號).

代碼:

public class ArrBinaryTree {
    public static void main(String[] args) {
        int[] a = {1, 2,3,4,5,6,7};
        ArrayBinaryTree arrayBinaryTree = new ArrayBinaryTree(a);
        arrayBinaryTree.preOrder(0);

    }
}

//
class ArrayBinaryTree {
    private int[] arr;

    public ArrayBinaryTree(int[] arr) {
        this.arr = arr;
    }

    //完成順序存儲二叉樹的前序遍歷
    //index 爲數組的下標
    public void preOrder(int index) {
        //如果數組爲空, 或者arr.length == 0
        if (arr == null || arr.length == 0) {
            System.out.printf("數組爲空,不能遍歷\n");
            return;
        }
        //先顯示自己
        System.out.println(arr[index]);

        //向左
        if ((index*2+1) < arr.length) {
            preOrder(2*index + 1);
        }

        //向右
        if ((index*2+2) < arr.length) {
            preOrder(2*index + 2);
        }
    }

}

2. 堆排序

堆排序使用完全二叉樹的性質:每個結點的值都大於或等於其左右孩子結點的值,稱爲大頂堆;
  每個結點的值都小於或者等於其左右孩子結點的值,稱爲小頂堆,這裏沒有要求結點的左右孩子結點的值的大小關係。
  平均時間複雜度爲:O(nlogn),不穩定排序

代碼:

public class HeapSortDemo {
    public static void main(String[] args) {
        //要求將數組進行升序排列
        int[] a = {4, 6, 8, 5, 9};
        heapSort(a);
        System.out.println(Arrays.toString(a));
    }


    //將數組調整成大頂堆
    public static void heapSort(int a[]) {
        int tmp = 0;
        System.out.println("堆排序");
        //變成大頂堆了
        for (int i = a.length/2 - 1; i >= 0; i --) {
            adjustHeap(a, i, a.length);
        }
        //將堆元素與末尾元素交換,最大元素沉到數組末端
        //重新調整結構,使其滿足堆定義,然後繼續將最大頂沉到數組末端
        for (int j = a.length-1; j > 0; j-- ) {
            tmp = a[j];
            a[j] = a[0];
            a[0] = tmp;

            adjustHeap(a, 0, j);
        }
    }

    /**
     *  完成將以i對應的非葉子結點的樹調整成大頂堆
     * @param a 待調整的數組
     * @param i 表示非葉子結點在數組中的索引
     * @param length 表示對多少個元素進行調整
     */
    //大堆向上冒泡,大的值往上冒
    public static void adjustHeap(int a[], int i, int length) {
        int tmp = a[i]; //保存當前非葉子結點的值
        /**
         * 1. k = i * 2 + 1 是i結點的左子結點
         */
        for (int k = i * 2 + 1; k < length; k = k*2 +1) {
            if ( k+1 < length && a[k] < a[k+1]) { //左子結點的值小於右子結點的值
                k++; //k 指向右子結點
            }
            if (a[k] > tmp) { //子結點大於父結點
                a[i] = a[k]; //把較大的值賦給當前結點
                i = k; // i指向k, 繼續循環比較
            } else {
                break;
            }
        }
        //一顆樹
        a[i] = tmp;
    }

}

 

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