堆结构和堆排序

1. 什么是堆 ?

2. 完全二叉树和数组前缀范围的对应

任何节点 i 的父亲节点 = (i - 1) / 2i 的左孩子 = i * 2 + 1i 的右孩子 = i * 2 + 2 

单独的变量size 来控制堆的大小, i * 2 + 1 < size 有左孩子、i * 2 + 2 < size 有右孩子

 

3. 向上调整大根堆、 向下调整大根堆

// 向上调整大根堆
    public static void heapInsert(int[] arr, int child) {
        int parent = (child - 1) / 2;
        while (arr[child] > arr[parent]) {
            swap(arr,child,parent);
            child = parent;
            parent = (child - 1) / 2;
        }
    }

    // 向下调整大根堆
    // 方法1:
    public static void heapify1(int[] arr, int parent, int size) {
        int child = parent * 2 + 1;
        while (child < size) {
            if (child + 1 < size && arr[child + 1] > arr[child]) {
                child++;
            }
            if (arr[child] > arr[parent]) {
                swap(arr,child,parent);
                parent = child;
                child = parent * 2 + 1;
            }else {
                break;
            }
        }
    }
    
    // 方法2:
    public static void heapify2(int[] arr, int p, int size) {
        int c = p * 2 + 1;
        while (c < size) {
            // 有左孩子
            // 选左右最大孩子
            int best = c + 1 < size && arr[c + 1] > arr[c] ? c + 1: c;
            best = arr[best] > arr[p] ? best : p;
            if (best == p) {
                break;
            }
            swap(arr,best,p);
            p = best;
            c = p * 2 + 1;
        }
    }

    public static void swap(int[] arr,int x,int y) {
        int tmp = arr[x];
        arr[x] = arr[y];
        arr[y] = tmp;
    }

 

4. 怎么把一颗完全二叉树改成 大/小根堆 ?

方法1:  向下调整建堆

方法2:  向上调整建堆

public static void createBigHeap(int[] arr) {
        // 向上调整建堆
        /*
        for (int i = 0;i < arr.length;i++) {
            heapInsert(arr,i);
        } */

        // 从最后一颗子树开始 向下调整建堆
        int parent = (arr.length - 1 - 1) / 2;
        for (int i = parent;i >= 0;i--) {
            heapify2(arr,i,arr.length);
        }
    }

 

5. 堆的删除与插入

public int poll() {
        int tmp = elem[0];
        Swap(0,usedSize-1);
        usedSize--;
        siftDown(0,usedSize);
        return tmp;
}

 

堆的插入:

public void offer(int data) {
        if (elem.length == usedSize) {
            this.elem = Arrays.copyOf(elem,elem.length*2);
        }
        elem[usedSize++] = data;
        siftUp(usedSize-1);
    }

 

6. 堆排序

大根堆排升序 小跟堆排降序

class Solution {

    // 向上调整大根堆
    public static void heapInsert(int[] arr, int child) {
        int parent = (child - 1) / 2;
        while (arr[child] > arr[parent]) {
            swap(arr,child,parent);
            child = parent;
            parent = (child - 1) / 2;
        }
    }

    // 向下调整大根堆
    public static void heapify1(int[] arr, int parent, int size) {
        int child = parent * 2 + 1;
        while (child < size) {
            if (child + 1 < size && arr[child + 1] > arr[child]) {
                child++;
            }
            if (arr[child] > arr[parent]) {
                swap(arr,child,parent);
                parent = child;
                child = parent * 2 + 1;
            }else {
                break;
            }
        }
    }

    public static void heapify2(int[] arr, int p, int size) {
        int c = p * 2 + 1;
        while (c < size) {
            // 有左孩子
            // 选左右最大孩子
            int best = c + 1 < size && arr[c + 1] > arr[c] ? c + 1: c;
            best = arr[best] > arr[p] ? best : p;
            if (best == p) {
                break;
            }
            swap(arr,best,p);
            p = best;
            c = p * 2 + 1;
        }
    }


    public static void createBigHeap(int[] arr) {
        // 向上调整建堆
        /*
        for (int i = 0;i < arr.length;i++) {
            heapInsert(arr,i);
        } */

        // 向下调整建堆
        int parent = (arr.length - 1 - 1) / 2;
        for (int i = parent;i >= 0;i--) {
            heapify2(arr,i,arr.length);
        }
    }

    public static void swap(int[] arr,int x,int y) {
        int tmp = arr[x];
        arr[x] = arr[y];
        arr[y] = tmp;
    }

    // 堆排序
    public static void heapSort(int[] arr) {
        createBigHeap(arr);
        int n = arr.length;
        while (n > 1) {
            swap(arr,0,--n);
            heapify1(arr,0,n);
        }
    }

    public static int[] sortArray(int[] nums) {
        if (nums.length > 1) {
            heapSort(nums);
        }
        return nums;
    }

    public static void main(String[] args) {
        int[] arr = {3,1,5,2,7};
        sortArray(arr);
    }
}

 

posted @ 2024-01-29 17:44  qyx1  阅读(21)  评论(0)    收藏  举报