First, let's describe the data structure of heap. The heap we are talking about now generally refers to the binary heap, so I will set the default heap as the binary heap. Heap is a fully filled Binary Tree, set the height of the tree to H, that is, from layer 1st to the H-1 layer, the node of the tree is filled, the only exception is at the bottom layer. If the bottom layer is filled from left to right, it is a complete binary tree. We can also use the full tree concept to define a full Binary Tree: A full Binary Tree is a one-to-one tree that corresponds to the full tree from left to right. Heap sorting is an unstable sorting algorithm. Its spatial complexity is O (1) and its time complexity is O (n * log2n ). A heap is divided into a large root heap and a small root heap. A large root heap means that the value of its parent node is always greater than that of its subnode. Because the heap is a full binary tree, the full binary tree is very regular, so we can use an array to store the full Binary Tree, instead of using a linked list for storage. While the storage in the array is a series of numbers, and the real structure in our hearts, we give this array several properties, then this array becomes a heap. For any node I in the heap, we can obtain the node of the left child is 2 * I, and the node of the right child is 2 * I + 1, that is, the node after the left child, the parent node is the next node of I/2. In this way, we need to write several function functions first. One is to get the left child node, the other is to get the right child node, the other is to get the parent node, and we need a hole location, this hole is the position next to the last available node, so we will use an swap space function. For functions that obtain nodes, we must use shift operations, which is more efficient than pure arithmetic operations. As for the third function swap, because the number in Java is passed by value, it is passed by array reference.
public static int getParent(int i) { return (i - 1) >> 1; } public static int GetLeftChild(int i) { return ((i + 1) <<1) - 1; } public static int GetRightChild(int i) { return (i + 1) <<1; } private static void swap(Object[] arr, int i, int j) { Object tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
Now we have written all the basic functions required. Now we can build a function to maintain the existence of heap features, this function means that the heap feature should be maintained from the first few nodes and Its subnodes, the heap that I wrote to maintain the heap feature is a large heap (that is, the element of the heap top ).
public static<T> void keepheap(T[] a, int i, Comparator <? super T> c, int size) { int l = getLeftChild(i); int r = getRightChild(i); int next = i; if (l < size && c.compare(a[l], a[i]) > 0) next = l; if (r < size && c.compare(a[r], a[next]) > 0) next = r; if (i == next) return; swap(a, i, next); keepheap(a, next, c, size); }
This function indicates that the heap is built from the I element until the left and right child nodes after the I and the nodes after the child nodes satisfy the definition of the big root heap and ends cyclically.
The following is a function to be written to build a heap. In the initial stage, we will provide any array. We need to first build a heap array and then filter the elements. The heap building process is a bottom-up process. Starting from the last parent node with a leaf node, we can use the list method to see that the parent node of the last leaf node is the length of the array (length)/2, that is, the location of the last parent node with leaf nodes.
public static <T> void buildHeap(T[] a, Comparator <? super T> c) { for (int i = (a.length + 1) / 2 - 1; i >= 0; i--) { keepheap(a, i, c,a.length); } }
Now we are going into the thought of heap sorting: the heap top element of the Big Top heap is the largest. Every time we exchange the heap top element with the last one, by default, the last element of the next loop is the previous element of the current last element, and the remaining elements except the last element constitute a heap, and so on, in this way, the entire array is an sorted array.
public static <T> void heapSort(T[] a, Comparator <? super T> c) { buildHeap(a, c); for (int i = a.length - 1; i > 1; i--) { swap(a, 0, i); keepheap(a, 0, c, i - 1); } }
Because the first element and the last element must be exchanged each time, in order to maintain the heap characteristics, the heap should be arranged again, and other elements except the root element will maintain the heap characteristics, the center controls the last element.