A special tree that satisfies the following two conditions:
1. The heap is always a complete binary tree (except for the last layer, all other nodes are full, and the last layer first arranges the left node)
2. The value of a node in the heap is always greater than or equal to (less than or equal to) the value of all its child nodes. If it is greater than or equal to, it is called large top pile, and if it is less than or equal to, it is small top pile.
A complete binary tree is suitable for array storage, because the subscript of an element with subscript I is 2I in its left subtree and 2I + 1 in its right subtree. The parent node is the overflow of I / 2.
Build pile
The heap is stored in an array, and the 0 subscript does not exist. It is stored from 1. The purpose of heap building is to exchange positions in place to achieve the purpose of heap building. In a complete binary tree, we know that if the subscript of the last element is n, then 1 to N / 2 are non leaf nodes and need to be stacked from top to bottom (compared with child nodes), and N / 2 + 1 to n are leaf nodes and do not need to be stacked.
Insert an element
First put the inserted element at the end of the heap, and then compare it with the parent node. If it is larger than the parent node, exchange the position, and then compare it with the parent node until the element is placed in the correct layer. This is also called bottom-up stacking.
Delete an element
If you delete the top of the heap, delete the largest element, and then find the second largest element in its child nodes and put it on the top of the heap. Look for the second largest element and then the next one
Heap sort
For example, if there are n data, we first build the data into a heap to generate a large top heap, and the number of elements is n
Get the top data (i.e. the largest element), delete the top, put the last element on the top, and then stack it into (n-1) large top heap. The time complexity of stacking is logn and the base is 2
Repeatedly obtain the top of the heap and stack it into (n-2) large top heap. The data we get is in the order from large to small.
Application of heap
Application 1: priority queue
Merge n ordered small files, take out the first element of N ordered small files, put it into the heap, take out the top of the heap to the large file, and then add one from the small file to the heap, so as to merge the elements of the small file into the large file.
Application 2: use heap to find top k (that is, find the top k data from a pile of data)
a. Create a small top heap with the size of K for static data (the data remains unchanged), traverse the array, compare the array element with the top of the heap, delete the top of the heap if it is larger than the top of the heap, and insert the element into the heap. B. compare the dynamic data (the data is constantly inserted and updated) with the top of the heap when inserting the dynamic data to see whether it is in the heap, always maintain the heap, and return it directly when necessary. The worst case is O (n * LGK)
Keyword search times: top3
a. First use hashtable to remove duplicates and accumulate the search times
b. Then create a small top heap of size k and traverse the hash table. If the number of times is greater than the top of the heap, replace the heap and push it into the heap (that is, apply the solution of 2)
When the hash table is large, it exceeds the memory requirements
-
Create n empty files, calculate the hash value of the search keyword, and take the modulus of n to obtain the file number (0 to n-1) to which the keyword is assigned
-
For each file, use hash and heap to find the TOPK respectively, and then put n topks together (for example, 10 top 20200 are very small). The K (20) keywords that appear most often are the most frequently searched in this massive data.
Go to realize large top reactor
type heap struct{
m []int
Len int // how many elements are there in the heap
}
func main() {
M: = [] int {0,9,3,6,2,1,7} // the zero subscript does not put the target element
H: = buildheap (m) // build heap and return a heap structure
h.Push(50)
h.Pop()
fmt.Println(h.m)
}
/**
Build on the original slice, that is, build on the original structure
As long as the nodes with slice subscripts n / 2 to 1 are stacked in order, the whole slice will be stacked at last
*/
func buildHeap(m []int) *heap{
n := len(m)-1
for i:=n/2; i>0; i-- {
heapf(m, n, i)
}
return &heap{m,n}
}
func (h *heap)Push(data int) {
h.len++
h. M = append (H.M, data) // insert data into the tail of the slice (infer that the subscript of the parent node is I / 2)
i := h.len
For I / 2 > 0 & & H.M [I / 2] < H.M [i] {// bottom-up heap
h.m[i/2], h.m[i] = h.m[i], h.m[i/2]
i = i/2
}
}
/**
Pop up the top element. In order to prevent array holes, you need to put the last element into the top of the heap and heap it from top to bottom
*/
func (h *heap)Pop() int{
if h.len < 1 {
return -1
}
out := h.m[1]
h. M [1] = H.M [h.len] // give the last element to the top of the heap
h.len--
//Pile up the top node
heapf(h.m, h.len, 1)
return out
}
//Heap the node with subscript i, and N represents the subscript of the last node in the heap
//2i,2i+1
func heapf(m []int, n,i int) {
for {
maxPos := i
if 2*i<= n && m[2*i] > m[i] {
maxPos = 2*i
}
if 2*i+1 <=n && m[2*i+1] > m[maxPos] {
maxPos = 2*i + 1
}
If maxpos = = I {// if the position of node I is correct, exit
break
}
m[i],m[maxPos] = m[maxPos],m[i]
i = maxPos
}
}
This work adoptsCC agreement, reprint must indicate the author and the link to this article