Binary Heap and Heap Sorting (Detailed Illustration)

Binary heap

Binary heap is a special tree with two characteristics:

  • Binary heap is a complete binary tree
  • The value of any parent node in the binary heap is greater than or equal to (or less than or equal to) the value of its left and right child nodes.

According to the second feature, binary stacks can be divided into two categories:

  • Maximum heap: The value of the parent node is always greater than or equal to the value of the left and right child nodes.
    Insert picture description here

  • Minimal heap: The value of the parent node is always less than or equal to the value of the left and right child nodes.
    Insert picture description here

Implementation of Binary Heap

1. Insert a node into the heap

Since the binary heap has the characteristics of a complete binary tree, when we insert a node, we should ensure that it is still a complete binary tree. Therefore, when inserting, we insert the new node into the last position of the binary heap. For example, insert 7 in the figure below.
Insert picture description here
Then adjust the binary heap so that any parent node is greater than or equal to its left and right child nodes. In this regard, we can float up the newly inserted node, that is, exchange positions with the parent node.

7 and 2, 7 is greater than 2, floating up.
Insert picture description here
The ratio of 7 to 5, 7 is greater than 5, floats up.
Insert picture description here
The ratio of 7 to 8, 7 is less than 8, the insertion is complete.
Insert picture description here

2. Delete the node

For a binary heap, to delete a node, we generally delete the root node. As with the insert operation, due to the characteristics of a complete binary tree of the binary heap, after the root node is deleted, the last element of the binary heap is replaced with the root node.
Insert picture description here
After deleting 8, replace 2.
Insert picture description here
To ensure that any parent node of the maximum heap is greater than or equal to the value of its left and right child nodes, the root node is sinked.
First, compare the values ​​of the left and right child nodes of the root node. 7 is greater than 6, and when comparing 2 with 7, 2 is less than 7, and it sinks.
Insert picture description here
Compare the values ​​of the left and right child nodes, 4 is greater than 2, the value of parent node 2 is less than 4, 2 and 4 are swapped.
Insert picture description here
Node 2 has no left and right child nodes, and the delete operation ends.
Insert picture description here

3. Build a binary heap

The construction of a binary tree is generally based on a linked list, but the binary heap is stored in an array.
Insert picture description here
The array corresponding to this binary heap is:
Insert picture description here
so if you know the location of a node, you can deduce the location of its left and right child nodes. If the subscript of a node is n, then the subscript of the left child node is: 2n+1, and the subscript of the right child node is: 2n+2.

Code implementation of the largest heap:

public class BinaryHeap {
    
    

    /**
     * 上浮操作,对插入的节点进行上浮
     *
     * @param arr
     * @param length 数组的长度
     */
    public static void upAdjust(int[] arr, int length) {
    
    
        // 标记插入的节点
        int child = length - 1;
        // 插入节点的父节点
        int parent = (child - 1) / 2;
        // 保存插入节点的值
        int temp = arr[child];

        // 进行上浮
        while (child > 0 && temp < arr[parent]) {
    
    
            // 单向赋值
            arr[child] = arr[parent];
            // 孩子节点和父节点向上移
            child = parent;
            parent = (child - 1) / 2;
        }

        // 循环结束,child的下标即时要插入的位置
        arr[child] = temp;
    }

    /**
     * 下沉操作
     *
     * @param arr
     * @param parent 要下沉元素的下标
     * @param length 数组的长度
     */
    public static void downAdjust(int[] arr, int parent, int length) {
    
    
        // 存储下沉元素的值
        int temp = arr[parent];
        // 下沉节点的孩子节点
        int child = parent * 2 + 1;

        while (child < length) {
    
    
            // 如果右孩子节点比左孩子节点大,定位到右孩子节点
            if (child + 1 < length && arr[child] < arr[child + 1]) child++;
            // 如果父节点大于等于孩子节点,退出循环
            if (temp >= arr[child]) break;

            // 单向赋值
            arr[parent] = arr[child];
            // 父节点和孩子节点向下移
            parent = child;
            child = parent * 2 + 1;
        }

        // 退出循环表示找到正确的位置
        arr[parent] = temp;
    }

    // 构建二叉堆
    public static void buildHead(int[] arr) {
    
    
        // 从最后一个非叶子节点开始下沉
        for (int i = (length - 2) / 2; i >= 0; i--) {
    
    
            downAdjust(arr, i, arr.length);
        }
    }
}

Heap sort

Heap sorting is implemented based on a binary heap. To achieve heap sorting, a binary heap needs to be constructed first. After the binary heap of size n is constructed, the element at the top of the heap is exchanged with the last element, the remaining n-1 elements are regarded as a new binary heap, and then the root node is sinked , Repeat this process to complete the heap sort. The diagram is as follows:
Insert picture description here
Exchange the top element 9 and the last element 2 of the heap.
Insert picture description herePerform a sinking operation on 2.
Insert picture description here
Exchange 7 with 1 and sink 1 for 1.
Insert picture description here
Exchange 6 with 2 and sink 2 for 2. During the sinking operation, if the left and right child nodes are the same, the left and right child nodes can be selected for exchange.
Insert picture description here
Exchange 5 with 3, and sink 3 for operation.
Insert picture description here
And so on... In
Insert picture description here
this way, the heap sort is complete.

The code is implemented as follows:

import java.util.Arrays;

public class HeapSort{
    
    

	 /**
     * 下沉操作
     * 
     * @param arr
     * @param parent  要下沉元素的下标
     * @param length  数组的长度
     */
    public static void downAdjust(int[] arr, int parent, int length) {
    
    
        // 保存要下沉元素的值
        int temp = arr[parent];
        // 定位左孩子节点的位置
        int child = parent * 2 + 1;

        while (child < length) {
    
    
            // 如果右孩子节点比左孩子节点大,则定位到右孩子节点
            if (child + 1 < length && arr[child] < arr[child + 1]) child++;
            // 如果父节点的值大于等于孩子节点的值,结束下沉操作
            if (temp >= arr[child]) break;

            // 单向赋值
            arr[parent] = arr[child];
            // 将父节点和孩子节点向下移
            parent = child;
            child = parent * 2 + 1;
        }

        // 循环结束表示定位到了正确位置
        arr[parent] = temp;
    }

    public static void heapSort(int[] arr) {
    
    
        if (arr == null || arr.length < 2) return;

        // 构建二叉堆,从最后一个非叶子节点开始下沉
        for (int i = (arr.length - 2) / 2; i >= 0; i--) {
    
    
            downAdjust(arr, i, arr.length);
        }

        // 进行堆排序
        for (int i = arr.length - 1; i > 0; i--) {
    
    
            // 将堆顶的元素和最后一个元素交换
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            // 下沉操作,每次数组的长度减一
            downAdjust(arr, 0, i);
        }
    }

	// 测试类
	public static void main(String[] args) {
    
    
        int[] a = new int[10];
        for (int i = 0; i < a.length; i++) {
    
    
            a[i] = (int) (Math.random() * 20);
        }

        System.out.println("排序前:" + Arrays.toString(a));
        heapSort(a);
        System.out.println("排序后:" + Arrays.toString(a));
    }
}    

operation result

排序前:[15, 19, 14, 8, 11, 4, 17, 16, 7, 19]
排序后:[4, 7, 8, 11, 14, 15, 16, 17, 19, 19]

Properties: ①Time complexity analysis: In the process of building a heap, the time complexity is O(n), and the time complexity in the sorting process is O(nlogn). Therefore, the overall time complexity of heap sorting is O(nlogn). ).

②Space complexity: O(1) ③In-situ sorting ④Unstable sorting

Guess you like

Origin blog.csdn.net/qq_46122005/article/details/110440480