Heap of data structure java version

Tomorrow is New Year 's Eve , here I wish everyone a prosperous new year 

content

1. Sequential storage of binary tree

1. Storage method

2. Subscript relationship

Second, the heap

1. Concept

2. Build a heap

3. Downward adjustment

Third, the application of the heap (priority queue)

1. Concept

2. Internal principle

3. Operation

①Enter the queue

②Out of the queue (highest priority)

③ Return to the first element of the team (the highest priority)

4. Other applications of heap - TopK problem


1. Sequential storage of binary tree

1. Storage method

  Use the array to save the binary tree structure, the method is to put the binary tree into the array by layer order traversal. Generally, it is only suitable for representing complete binary trees, because non-complete binary trees will waste space. That is to say, using a heap to represent it is to use a complete binary tree to represent it.

As can be seen from the figure, for a non-complete binary tree, a lot of space is wasted. Therefore, the representation of the heap uses the representation method of the complete binary tree.

2. Subscript relationship

①Under known parents:

left child(left) subscript = 2 * parent + 1;

right child (right) subscript = 2 * parent + 2;

② Known children (without distinguishing left and right) (child) subscript:

Parent subscript = (child - 1) / 2

Second, the heap

1. Concept

①The heap is logically a complete binary tree

②The heap is physically stored in the array

③ Satisfy that the value of any node is greater than the value of the node in its subtree, which is called a large heap, or a large root heap, or a maximum heap

(Note: all subtrees in the entire tree must meet this condition)

④ On the contrary, it is a small heap, or a small root heap, or a minimum heap (note: all subtrees in the entire tree must meet this condition)

⑤ The basic function of the heap is to quickly find the most value in the set

2. Build a heap

reflected in the following operations

3. Downward adjustment

Important: The left and right subtrees must already be a heap in order to be adjusted. Take a large heap as an example, and finally adjust it into the form of a large root heap

①The adjustment starts from the last subtree

②Each subtree is adjusted downwards

? ? ? question? ? ?

①How to find the subtree of the last tree

 As mentioned earlier: (len-1) can find the index of the last subtree; and

parent=((len-1)-1)/2

②How to traverse

parent-- you can traverse each subtree

③How to realize

Implemented with a downward adjustment function

④How to determine the position where the adjustment of each tree ends?

The end position of each tree adjustment is actually the same len

Specific implementation ideas: 

code show as below:

public class TestHeap {
    public int []elem;
    //用来记录实际放入数组的元素个数
    public int usedSize;
    public TestHeap(){
        this.elem=new int[10];
    }//向下调整
    //parent:每棵树的根结点
    //len:每棵树调整的结束位置
    public void shiftDown(int parent,int len) {
        int child = parent * 2 + 1;
        //该子树至少有一个左孩子
        while (child < len) {
            if (child + 1 < len && elem[child] < elem[child + 1]) {
                //用来保证取的值是当前左右孩子中较大值的下标
                child++;
            }//情况①,elem[c]>elem[p]且p,c需要继续向下检测
            if (elem[child] > elem[parent]) {
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                parent = child;
                child = 2 * parent + 1;
            }//情况②,elem[c]<elem[p],其子树也必然为大根堆,所以可以直接退出循环
            else {
                break;
            }
        }
    }
            //创建大根堆
            public void createHeap( int[] array){
                for (int i = 0; i < array.length; i++) {
                    elem[i] = array[i];
                    this.usedSize++;
                }
                for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; parent--) {
                    //向下调整
                    shiftDown(parent, usedSize);
                }
            }
    }

Time complexity analysis:

A rough estimate can be considered as performing downward adjustment in the loop, which is O(n * log(n)) (understand) is actually O(n) How does the time complexity of the heap building process in heap sorting O(n) come from ?

You can refer to this article, which will not be explained in detail here.

How does the time complexity O(n) of the heap construction process in heap sorting come from? - Know (zhihu.com) https://www.zhihu.com/question/20729324

Third, the application of the heap (priority queue)

1. Concept

In many applications, we usually need to process the objects to be processed according to the priority situation, for example, the object with the highest priority is processed first, and then the object with the second highest priority is processed. The simplest example is that when playing a game on a mobile phone, if there is an incoming call, the system should give priority to the incoming call. In this case, our data structure should provide two most basic operations, one to return the highest priority object and one to add a new object.

This data structure is the Priority Queue

2. Internal principle

There are many ways to implement priority queues, but the most common is to use the heap to build. 

3. Operation

①Enter the queue

Problem-solving ideas: (essentially an upward adjustment)

① Put the elements to be enqueued at the end of the queue, and expand the capacity if the original queue is full

②Find the node and its parent node, compare the values ​​of the two, if elem[child] > elem[parent], then exchange, otherwise exit the loop

③Note: Because the original tree has been adjusted, you only need to compare with the parent node of each subtree when entering the team at this time, and the condition for the end of the cycle is child<0;

Code:

//向上调整
    private void shiftUp(int child) {
        int parent = (child-1)/2;
        while (child > 0) {
            if(elem[child] > elem[parent]) {
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child-1)/2;
            }else {
                break;
            }
        }
    }

    public void offer(int val) {
        if(isFull()) {
            //扩容
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize++] = val;
        //此处传入的是下标值,因此注意这里传入的是usedSize-1
        shiftUp(usedSize-1);
    }

    public boolean isFull() {
        return usedSize == elem.length;
    }

②Out of the queue (highest priority)

Note: Each time you dequeue, you must ensure that the largest or smallest

Problem solving ideas:

①Swap the 0 subscript and the last element

② Adjust the 0 subscript to this tree (adjust downward)

code show as below:

 public int poll(){
        if(isEmpty()){
            throw new RuntimeException("此优先队列为空!");
        }int tmp=elem[0];
        elem[0]=elem[usedSize--];
        elem[usedSize--]=tmp;
        usedSize--;
        shiftDown(0,usedSize);
        return tmp;
    }
    public boolean isEmpty(){
        return usedSize==0;
    }

③ Return to the first element of the team (the highest priority)

 public int peek(){
        if(isEmpty()){
            throw new RuntimeException("此优先队列为空!");
        }
        return elem[0];
    }

4. Other applications of heap - TopK problem

will be covered in the next section of the blog

                                                              

Guess you like

Origin blog.csdn.net/weixin_58850105/article/details/122708870