I have a pile in my heart

heap

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收**藏 ^ _ ^ !

  1. There is a pile in my heart https://blog.csdn.net/luo_boke/article/details/106928990
  2. There is a tree in the heart-basic https://blog.csdn.net/luo_boke/article/details/106980011
  3. There is a stack in my heart https://blog.csdn.net/luo_boke/article/details/106982563

Heap is a complete binary tree , a sorted tree data structure, which satisfies the following properties:

  1. Heap sequence: the value of any node is less than (or greater than) the value of all its descendants, and the minimum node (or maximum node) is at the root of the heap.
  2. Structural: The heap is always a complete binary tree, that is, except for the bottom layer, the nodes of other layers are filled with elements, and the bottom layer is filled as much as possible from left to right.

What is a binary tree? Please check my other blog post "Tree in Heart-Basics"

Small root heap and large root heap
Small root heap: The heap whose node value is less than the value of the descendant node, also called the minimum heap, the left of
the figure Big root heap: The heap with the node value greater than the value of the descendant node, also called the largest heap, the right of the figure
Insert picture description here

Binary heap
Binary heap is a special kind of heap, that is, each node has no more than 2 child nodes. Heap sort is the binary heap used.

Heap storage
generally uses linear data structures (such as arrays) to store the heap:
Insert picture description here

  • The root node is stored in the 0th position
  • The left child of node i is stored at 2*i+1
  • The right child of node i is stored at 2*i+2

Heap build process

1) Push the parent node according to the child node: (n-1)/2
2) Push the child node according to the parent node: left child node (2n+1), right child node (2n+2)
index by 0 starts counting

We build a large root pile with 10 numbers of 9, 12, 5, 24, 0, 1, 99, 3, 10, 7 as follows,

  1. First of all, we regard the current unordered sequence as a heap structure, a binary tree with no rules, and fill the binary tree with the values ​​in the sequence from top to bottom and from left to right.
    Insert picture description here
  2. Traverse the parent node from the last leaf 7. If the parent <the maximum value of the left and right child nodes, the value of the parent node is exchanged with the maximum child node. Find that 7 and 10 are both less than 35, switch to the parent node of 99 and 3, find that 99>24, exchange the positions of 24 and 99.
    Insert picture description here
  3. Continue to compare the parent nodes of 0 and 1, because 0<5, 1<5, go down to compare the parent nodes of 99 and 35, the largest child node 99>12, exchange positions. After the exchange, the parent node of 12 needs to be sorted, and it is found that 24>12, and the positions of 12 and 24 need to be exchanged.
    Insert picture description here
    Insert picture description here
  4. Continue to traverse the parent node 9, and need to change positions with 99. Similarly, 9 needs the largest child node 35 to change positions.
    Insert picture description here
  5. Finally got a lot of root
    Insert picture description here
    build code

    /***
     * 构建大根堆
     * @param array  数据源
     */
    private void buildHeap(int[] array) {
    
    
        //从右向左,从下到上依次遍历父结点,建立大根堆,时间复杂度:O(n*log2n)
        for (int i = (array.length - 1 - 1) / 2; i >= 0; i--) {
    
    
            adjust(array, i, array.length - 1);
        }
    }
    
    /**
     * 将指定堆构建成大堆根函数
     * 逻辑
     * 1. 如果起始索引无子结点,则跳出该方法
     * 2. 如果只有一个左子结点,进行大小比较并置换值
     * 3. 如果有两个子结点,选择最大值与父结点比较,然后置换其位置。
     * 如果子结点大于父结点,置换完成后,递归进行同样操作,其子结点索引即是函数的start值
     *
     * @param array 源数组
     * @param start 起始索引
     * @param end   结尾索引
     */
    public void adjust(int[] array, int start, int end) {
    
    
        // 左子结点的位置
        int leftIndex = 2 * start + 1;
        if (leftIndex == end) {
    
    
            //只有一个左结点,进行比较并置换值
            if (array[leftIndex] > array[start]) {
    
    
                int temp = array[leftIndex];
                array[leftIndex] = array[start];
                array[start] = temp;
            }
        } else if (leftIndex < end) {
    
    
            //有两个子结点
            int temp = array[leftIndex];
            int tempIndex = leftIndex;
            if (array[leftIndex + 1] > array[leftIndex]) {
    
    
                temp = array[leftIndex + 1];
                tempIndex = leftIndex + 1;
            }
            if (temp > array[start]) {
    
    
                array[tempIndex] = array[start];
                array[start] = temp;
            }
            adjust(array, tempIndex, end);
        }
    }

Heap sort process

We have built the big root heap above, and now we sort the heap. The construction idea is:

  1. Compile according to the characteristics of the heap, first construct a set of data with n elements into a large root heap or a small root heap (I introduce it according to the big root heap, and the small root heap is the same idea).
  2. Then exchange the number on the root node with the last digit of the heap. At this time, the nth digit is the largest number in the entire sequence.
  3. Then construct the first n-1 as elements to form a large root pile, and then exchange the root node with the n-1th bit data to obtain the second largest data. At this time, the last two data are undoubtedly in order.
  4. Then construct the first n-2 data into a big root pile, and loop until there is one element left, indicating that the numbers after the first digit are ordered and larger than the first digit, and the sorting is complete.
  • 1) Replace 99 with 7 and rebuild the big root heap for the heap that excludes 99
    Insert picture description here
  • 2) Replace the positions of 35 and 9, and rebuild the roots of the remaining 8 numbers
    Insert picture description here
  • 3) Exchange positions of 24 and 3, and rebuild the big root pile for the remaining 7 numbers
    Insert picture description here
  • 4) The follow-up process is the same, and finally the sorted heap 0, 1, 3, 5, 7, 9, 10, 12, 24, 35, 99 is obtained
    Insert picture description here

Sort code

    /**
     * 堆排序
     *
     * @param array 源数组
     */
    public void heapSort(int[] array) {
    
    
        buildHeap(array);
        int tmp;
        //要与root结点置换位置元素的索引
        int end = array.length - 1;
        //n个结点只用构建排序n-1次,最后只有1个元素不用在排序
        for (int i = array.length - 1; i > 0; i--) {
    
    
            tmp = array[0];
            array[0] = array[end];
            array[end] = tmp;

            end--;
            //头尾置换后,将堆重新构建为大堆根,置换尾部大元素不参加构建
            //因为除了root结点,其他都是由大到小有序的,所以再次构建大根堆时,不用在进行adjust()前的那个循环
            adjust(array, 0, end);
        }
    }

Heap add element

When adding elements, new elements are added to the end of the array, but after adding elements, the nature of the heap may be destroyed, and the heap result needs to be adjusted upwards . Such as adding element 100 to a large pile of root piles.
Insert picture description here
At this time, the structure of the pile is destroyed and needs to be adjusted from bottom to top. Because 100 is greater than 0,5,99, the new root is
Insert picture description here
元素添加代码

    /**
     * 在 array 是大堆根的前提下添加元素然后重构大堆根
     *
     * @param array 大堆根数组
     * @param value 添加的元素值
     */
    private void addHeap(int[] array, int value) {
    
    
        int[] arr = new int[array.length + 1];
        System.arraycopy(array, 0, arr, 0, array.length);
        arr[arr.length - 1] = value;
        int currentIndex = arr.length - 1;
        int parentIndex = (arr.length - 1) / 2;
        while (parentIndex >= 0) {
    
    
            if (value > arr[parentIndex]) {
    
    
                int temp = arr[parentIndex];
                arr[parentIndex] = value;
                arr[currentIndex] = temp;

                //如果最后一个元素的父结点还有父结点需要继续进行对比
                currentIndex = parentIndex;
                parentIndex = (currentIndex - 1) / 2;
            } else {
    
    
                break;
            }
        }
    }

Heap delete element

Heap deletion elements are all deleted from the node, and then the last element of the array with this node as the root node is moved to the position of the root node, and the heap structure is adjusted downwards until the heap order is again met. If we delete node 35, move 7 to the position of 35 and
Insert picture description here
compare 7 with its child nodes one by one until it meets the big root pile rule
Insert picture description here

Delete element code

/**
     * 在 array 是大堆根的前提下删除元素然后重构大堆根
     *
     * @param array 大堆根数组
     * @param deleteIndex 删除元素的索引
     */
    private int[] deleteHeap(int[] array, int deleteIndex) {
    
    
        array[deleteIndex] = array[array.length - 1];
        int[] arr = new int[array.length - 1];
        System.arraycopy(array, 0, arr, 0, array.length - 1);
        int lefeIndex = 2 * deleteIndex + 1;
        while (lefeIndex >= arr.length - 1) {
    
    
            int maxIndex = lefeIndex;
            if (arr.length - 1 > lefeIndex) {
    
    
                if (arr[lefeIndex + 1] > arr[lefeIndex]) {
    
    
                    maxIndex = lefeIndex + 1;
                }
            }

            if (arr[maxIndex] > arr[deleteIndex]) {
    
    
                int temp = arr[maxIndex];
                arr[maxIndex] = arr[deleteIndex];
                arr[deleteIndex] = temp;
                lefeIndex = 2 * maxIndex + 1;
            } else {
    
    
                break;
            }
        }
        return arr;
    }

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收**藏 ^ _ ^ !

Related Links

Guess you like

Origin blog.csdn.net/luo_boke/article/details/106928990