In the “Java collection framework” in the last article, there is still one big problem that has not been mentioned, that is, priority queue, heap.

## What is heap?

Heap is actually a special kind of queue priority queue.

The ordinary queue game rule is very simple: first in first out; but this kind of priority queue**Special**, not in chronological order, but in order of each element**priority**To compete,**The highest priority is at the top of the heap**。

This is also easy to understand, for example, all kinds of software have membership system, a software can speed up the download with members, the speed of different levels of members is not the same, that is, the priority is different.

In fact, everyone’s reply to wechat message is also silently put the message into the pile in a sequence: first back to the boyfriend and girlfriend, and then back to other people’s.

This is different from the “heap” in the operating system. Although these two are called heaps, they have nothing to do with each other. They all borrow the English word heap.

Let’s review**heap**“In the entire Java collection framework:

in other words,

- PriorityQueue is a class;
- PriorityQueue inherits from the interface of queue;

<span style=” display:block;color : blue; “> Where is the heap?

Heap is actually a**Abstract data structure**Or is it**Logical data structure**, is not a physical real data structure.

<span style=”; color:blue; “> heap can be realized in many ways, < / span > for example, binary heap, Fibonacci heap and so on. But the most common and classic interview is**Binary heap**That is to say, use a tree**Complete binary tree**To achieve.

<span style=” display:block;color : blue; “> how to realize complete binary tree?

In fact, it’s using**array**Come true!

#### So binary heap / PriorityQueue actually uses**array**To achieve.

This array is arranged in a special way, because it always maintains what you define (or default)**Highest priority element**It’s at the top of an array, so not every array is called “heap”. In fact, it should be a “complete binary tree” in your mind.

This complete binary tree only exists in your heart and in books. Actually, it is in memory. What tree is there? It’s just an array.

So why can a complete binary tree be implemented with arrays? Can all trees be implemented with arrays?

This involves the nature of the complete binary tree. We will talk about it in detail in the next article. Simply speaking, the definition of the complete binary tree requires that it has no bubbles when traversing the sequence, that is, it can be stored continuously, so it can be stored in arrays. The second question is whether or not.

## The characteristics of stack

- Heap is a complete binary tree;
- Heap order: any node can
**be better than**its**All the kids**。a. If it’s any node, it’s OK

**greater than**All its children, this pile is called**Big top reactor**，Max Heap;b. If it’s any node, it’s OK

**less than**All its children, this pile is called**Small top pile**，Min Heap;

On the left is the small top heap. You can see that for each node, it is smaller than that of all its children. Note that**All children, including grandchildren, great grandchildren**

- Now that the heap is implemented as an array, we can find the relationship between each node and its parent / child so that we can access them directly.

For example, for node 3,

- Its index = 1,
- Its parent index = 0,
- Left child index = 3,
- Right child index = 4

It can be concluded as follows

- Let the index of the current node be X,
- Then parent index = (x-1) / 2,
- Left child index = 2 * x + 1,
- Right child index = 2 * x + 2

Some books may have a slightly different way of writing, because their array starts from 1, while the subscript of the array here starts from 0, which is OK.

In this way, you can find its grandson and great grandson from any point in one step. It’s really convenient. When we talk about the specific operation later, we can have a deeper understanding.

## basic operation

Any data structure is nothing more than four categories of addition, deletion, modification and query

function | method | Time complexity |
---|---|---|

increase | offer(E e) | O(logn) |

Delete | poll() | O(logn) |

change | No direct API | Delete + add |

check | peek() | O(1) |

here`peek()`

The time complexity of this step is easy to understand, because the purpose of heap is to quickly get the maximum / minimum value in a set of data, so the time complexity of this step must be zero`O(1)`

Yes, that’s what heap means.

Let’s look at it in detail`offer(E e)`

and`poll()`

It’s a process of change.

## offer(E e)

For example, let’s add a new one`0`

To the smallest pile just now:

It’s obvious that 0 should be placed on the top, but it’s not a complete binary tree to put it directly..

So

- Let’s make sure that after adding elements, the tree is still a complete binary tree,
- And then fine-tuning through swap to meet the heap order.

That’s the guarantee**Two characteristics of heap are satisfied**That is, after adding new elements**It’s also a pile**。

How to do it

#### Step 1.

Put 0 at the end first, don’t think about the upper position as soon as you come up;

OK！ Finally, we got ashore first, and then we went up step by step.

The criteria for “going up” are as follows:**Is heap order satisfied**。

That is to say, if 5 and 0 do not satisfy heap order, then swap positions,**Switch to until heap order is satisfied**。

The heap order for the smallest heap here is**The small number should be on it**。

#### Step 2. Exchange with 5

At this point, 0 and 3 do not meet the heap order, then swap again.

#### Step 3. Exchange with step 3

Not yet. 0 is smaller than 1, so keep changing.

#### Step 4. Exchange with 1

OK！ In this way, a new heap is born

To summarize this method:

**First add the new element to the end of the array, and then compare with the value of parent to decide whether to exchange or not until the heap order is satisfied.**

This is the process`siftUp()`

The source code is as follows:

#### Time complexity

It’s not hard to find that we only exchange elements on one branch,

That is, the most exchange`O(height)`

Times.

So for a complete binary tree, except for the last layer, it is full,`O(height) = O(logn)`

。

therefore`offer(E e)`

The time complexity is`O(logn)`

la

## poll()

`poll()`

That’s to take the top element away.

By the way, there’s no way to take away the elements in the middle. After all, the VIP must go out first, so the younger brother can go out.

After the top element is removed, the position will be empty:

We’d better satisfy the order of the pile first, because it’s easier to satisfy. Just take one from the last side to make it up, and put a puppet first.

#### Step 1

In this way, the heap order is not satisfied, and elements are exchanged.

8 is bigger than 7 and 3. Who should I exchange it with?

Suppose that 7 is exchanged with 7, then 7 is still bigger than 3, and 7 and 3 have to be exchanged, which is troublesome.

So it’s with the left and right children**less**The exchange of the two.

#### Step 2. Exchange with step 3

After going down, it’s bigger than 5 and 4. Then change with 4.

#### Step 3. Exchange with step 4

OK！ So the tree is stable at last.

To summarize this method:

**First, add the last element of the array to the top, and then compare the values with the left and right children to decide whether to exchange or not until the heap order is satisfied.**

This is the process`siftDown()`

The source code is as follows:

#### Time complexity

In the same way, only the elements on one branch are exchanged, that is, the most exchange`O(height)`

Times.

therefore`offer(E e)`

The time complexity is`O(logn)`

la

## heapify()

There is also a famous and very important operation, that is`heapify()`

Now, it’s a magic operation,

#### You can use it`O(n)`

Time to turn an out of order array into a heap.

But,`heapify()`

It’s not a public API

So we have no way to use it directly.

Only use`heapify()`

The best way is to use`PriorityQueue(Collection<? extends E> c)`

When using this constructor, people will call heapify () automatically.

<span style=” display:block;color : blue; “> how to do it?

Ha ha, the source code has been exposed

#### Start with the last non leaf node and work from back to front`siftDown()`

.

Because there’s no need to operate the leaf node. It’s at the bottom. Who else can I swap with?

for instance:

We want to do this array`heapify()`

Operation, want to turn it into a minimum heap, get its minimum value.

So we have to start with 3, and we have to start with 3, 7 and 5`siftDown()`

.

#### Step 1.

Embarrassed, 3 doesn’t need to be exchanged, because the little tree with it as its vertex has met the heap order.

#### Step 2.

7 is older than its two children, so trade with the younger one.

After the exchange;

#### Step 3.

The last thing to deal with is 5. Here 5 is older than its two children, so I’d like to exchange it with the younger one.

After replacement, the result is as follows. Note that the heap order is not satisfied, because 4 is smaller than 5.

So we change it to 4, and the result is as follows:

So the whole thing`heapify()`

That’s it.

#### Well, here comes the difficulty. Why is the time complexity O (n)?

How to calculate the time complexity?

In fact, what we do in this process is nothing more than exchange.

How many times have they exchanged?

Yes, the time complexity is the number of exchanges.

So we can see that, in fact**Nodes on the same layer**The maximum number of exchanges is the same.

**Then the total number of exchanges = the number of nodes in each layer * the maximum number of exchanges per node**

Let K be the number of layers. In this example, k = 3

**The number of nodes in each layer increases exponentially from top to bottom**

$$\ce{1, 2, 4, …, 2^{k-1}}$$

**The number of exchanges per node,**

From the bottom up:

$$ 0, 1, …, k-2, k-1 $$

**So the total number of exchanges S(k)It’s multiplication and addition**

$$S(k) = \left(2^{0} *(k-1) + 2^{1} *(k-2) + … + 2^{k-2} *1 \right)$$

This is a series of equal ratio and difference, and the standard way of summation is**Offset subtraction**。

that

$$2S(k) = \left(2^{1} *(k-1) + 2^{2} *(k-2) + … + 2^{k-1} *1 \right)$$

By subtracting the two, we get:

$$S(k) = \left(-2^{0} *(k-1) + 2^{1} + 2^{2} + … + 2^{k-2} + 2^{k-1} \right)$$

Simplify:

Sorry, I can’t stand this editor…

therefore`heapify()`

What is the time complexity`O(n)`

.

These are the three important operations of the heap, the last one`heapify()`

Although it can’t be operated directly, this idea is used in heap sorting. The previous article “selective sorting” also mentioned some. Interested students can reply “selective sorting” in the background to get the article. As for the specific implementation and application of heap sorting, and why they don’t like it in actual production, we will talk about it later.

Finally, another digression. Recently, I found a few articles transporting my articles to other platforms. Every article is my carefully made, are their own darling, see others directly carry in the past, also did not indicate the author and source is too sad.. For the best reading experience, I didn’t add watermarks to all the pictures in this article, but it’s also convenient for others to carry. I think about it again and again today, but I still don’t want to go against my original intention. After all, my readers are more important.

So if you see it later, please let me know from the background or wechat. Thank you very much!

I have the same name on each platform, please recognize “code farmland Xiaoqi” ～

If you like my articles or have something to gain, please give me a “like” or “watching” to give me a little encouragement. It will make me happy for a long time

If you want to play with me in algorithm and interview, please pay attention to me. I’m Xiao Qi. See you next time.