Before learning heap sorting, you first need to understand the meaning of heap: in a sequence containing n elements, if the elements in the sequence meet one of the following relationships, the sequence can be called heap.
- ki ≤ k2i And ki ≤ k2i+1 (within the range of n records, the value of the ith keyword is less than the 2nd * I keyword and also less than the 2nd * I + 1 keyword)
- ki ≥ k2i And ki ≥ k2i+1 (within the range of n records, the value of the ith keyword is greater than the 2nd * I keyword and also greater than the 2nd * I + 1 keyword)
For the definition of heap, you can also use full Binary tree Because in a complete binary tree, the left child of the ith node happens to be the 2i node and the right child happens to be the 2i+1 node. If the sequence can be called heap, the value of each root node in the complete binary tree constructed by using the sequence must not be less than (or greater than) the value of about child nodes.
In terms of the unordered table {49, 38, 65, 97, 76, 13, 27, 49}, the corresponding heap is represented by a complete binary tree as follows:
Figure 3 heap corresponding to unordered table
Tip: when the heap is represented by a complete binary tree, its representation method is not unique, but it can be determined that the root node of the tree is either the minimum value or the maximum value in the unordered table.
By converting an unordered table into a heap, you can directly find the maximum or minimum value in the table, and then extract it, so that the remaining records can rebuild a heap, and take out the second largest value or the second smallest value. In this way, an ordered sequence can be obtained by repeated execution. This process is heap sequencing.
The code implementation of heap sorting process needs to solve two problems:
- How to convert the obtained unordered sequence into a heap?
- After outputting the top elements of the heap (the root node of the complete binary tree), how to adjust the remaining elements to build a new heap?
First, solve the second problem. Figure 3 shows a complete binary tree. If the heap top element is removed, the tree root node of the binary tree is deleted. At this time, the last node 97 in the binary tree is used instead, as shown in the following figure:
At this time, node 97 is larger than the values of the left and right child nodes, which destroys the heap structure. Therefore, it needs to be adjusted: first, compare the heap top element 97 with the left and right subtrees, and the node exchange position with the lowest same value, that is, the exchange positions of 27 and 97:
Since the heap structure of the right subtree of the root node is destroyed after replacement, the same adjustment needs to be made as above, that is, 97 and 49 exchange positions:
Through the above adjustment, the previously damaged reactor structure is re established. The whole adjustment process from root node to leaf node is called "filtering".
The first problem is solved by using the continuous filtering process, as shown in the figure below. The unordered table {49, 38, 65, 97, 76, 13, 27, 49} preliminarily establishes a complete binary tree, as shown in the figure below:
When filtering the above figure, the rule is from the bottom node to the root node. For a complete binary tree with n nodes, the node at the beginning of the filtering work is the ⌊ n/2 ⌋ (this node is a leaf node in the subsequent order, so there is no need to filter).
Therefore, for a complete binary tree with 9 nodes, the filtering starts from the fourth node 97. Since 97 > 49, it needs to be exchanged with each other. After exchange, it is shown in the figure below:
Then filter the third node 65. Since 65 is larger than the left and right child nodes, select the smallest one to exchange with 65. The exchange result is:
Then, the second node is filtered. Because it meets the requirements, it does not need to be filtered; Finally, the root node 49 is selected and exchanged with 13. The exchange result is:
After the exchange, it is found that the structure of the right subtree heap is damaged, so it needs to be adjusted. The final adjustment result is:
Therefore, the complete code for heap sorting is:
#include <stdio.h> #include <stdlib.h> #define MAX 9 //Structure of a single record typedef struct { int key; }SqNote; //Structure of record table typedef struct { SqNote r[MAX]; int length; }SqList; //The subtree with r[s] as the root node forms a heap, and the value of each root node in the heap is greater than that of its child node void HeapAdjust(SqList * H,int s,int m){ SqNote rc=H->r[s];//First, save the node data at the operation position, and then move the element after placing it. The element is lost. //For the s-th node, filter until the end of the leaf node for (int j=2*s; j<=m; j*=2) { //Find the child node with the largest value if (j+1<m && (H->r[j].key<H->r[j+1].key)) { j++; } //If the current node is larger than the value of the largest child node, you do not need to filter this node and skip it directly if (!(rc.key<H->r[j].key)) { break; } //If the value of the current node is smaller than the maximum value of the child node, the maximum value will be moved to the node. Since rc records the value of the node, the value of the node will not be lost H->r[s]=H->r[j]; s=j;//s is equivalent to a pointer, pointing to its child node to continue filtering } H->r[s]=rc;//Finally, you need to add the value of rc to the correct position } //Swap the location of two records void swap(SqNote *a,SqNote *b){ int key=a->key; a->key=b->key; b->key=key; } void HeapSort(SqList *H){ //The process of building a heap for (int i=H->length/2; i>0; i--) { //Filter the root nodes with child nodes HeapAdjust(H, i, H->length); } //By constantly filtering the maximum value, while constantly filtering the remaining elements for (int i=H->length; i>1; i--) { //The exchange process is to save the selected maximum value at the end of the large table, and replace it with the element at the last position, so as to prepare for the next filtering swap(&(H->r[1]), &(H->r[i])); //Filter the next maximum HeapAdjust(H, 1, i-1); } } int main() { SqList * L=(SqList*)malloc(sizeof(SqList)); L->length=8; L->r[1].key=49; L->r[2].key=38; L->r[3].key=65; L->r[4].key=97; L->r[5].key=76; L->r[6].key=13; L->r[7].key=27; L->r[8].key=49; HeapSort(L); for (int i=1; i<=L->length; i++) { printf("%d ",L->r[i].key); } return 0; }
The operation result is:
13 27 38 49 49 65 76 97
Tip: in the code, in order to reflect the process of building the heap and rebuilding the heap after outputting the top elements of the heap, the second relationship of the heap is adopted in the process of building the heap, that is, the value of the parent node is greater than that of the child node; The same is true of the process of rebuilding the heap.
Heap sorting in the worst case, its Time complexity Still O(nlogn). This is relative to Quick sort The advantages of. At the same time, compared with tree selection sort, heap sort only needs an auxiliary storage space for record exchange (rc), which is smaller than the running space of tree selection sort.
Data structure heap sorting tutorial:
I have a programming learning group, which has all kinds of C/C + + project materials, tutorials and source code. Welcome to learn and exchange together~
Scan the QR code below to enter