Can’t you tell a pile from a fool? This article tells you the best way to open heap in Java collection

Time:2021-1-27

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 queueSpecial, not in chronological order, but in order of each elementpriorityTo 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.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

Let’s reviewheap“In the entire Java collection framework:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 aAbstract data structureOr is itLogical 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 isBinary heapThat is to say, use a treeComplete binary treeTo achieve.

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

In fact, it’s usingarrayCome true!

So binary heap / PriorityQueue actually usesarrayTo achieve.

This array is arranged in a special way, because it always maintains what you define (or default)Highest priority elementIt’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

  1. Heap is a complete binary tree;
  2. Heap order: any node canbe better thanitsAll the kids

    a. If it’s any node, it’s OKgreater thanAll its children, this pile is calledBig top reactor,Max Heap;

    b. If it’s any node, it’s OKless thanAll its children, this pile is calledSmall top pile,Min Heap;

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 thatAll children, including grandchildren, great grandchildren

  1. 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.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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)

herepeek()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 zeroO(1)Yes, that’s what heap means.

Let’s look at it in detailoffer(E e)andpoll()It’s a process of change.

offer(E e)

For example, let’s add a new one0To the smallest pile just now:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 guaranteeTwo characteristics of heap are satisfiedThat is, after adding new elementsIt’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;

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 isThe small number should be on it

Step 2. Exchange with 5

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Step 3. Exchange with step 3

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Step 4. Exchange with 1

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 processsiftUp()The source code is as follows:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

Time complexity

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

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

That is, the most exchangeO(height)Times.

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

thereforeoffer(E e)The time complexity isO(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:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 childrenlessThe exchange of the two.

Step 2. Exchange with step 3

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Step 3. Exchange with step 4

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 processsiftDown()The source code is as follows:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

Time complexity

In the same way, only the elements on one branch are exchanged, that is, the most exchangeO(height)Times.

thereforeoffer(E e)The time complexity isO(logn)la

heapify()

There is also a famous and very important operation, that isheapify()Now, it’s a magic operation,

You can use itO(n)Time to turn an out of order array into a heap.

But,heapify()It’s not a public API

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

So we have no way to use it directly.

Only useheapify()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 frontsiftDown().

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

for instance:

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

We want to do this arrayheapify()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 5siftDown().

Step 1.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Step 2.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

After the exchange;

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

So the whole thingheapify()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 factNodes on the same layerThe 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

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

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 exchangesS(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 isOffset 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…

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

thereforeheapify()What is the time complexityO(n).

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection

These are the three important operations of the heap, the last oneheapify()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.

Can't you tell a pile from a fool? This article tells you the best way to open heap in Java collection
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.