Queue (queue) interface, and its implementation class PriorityQueue (priority queue) parsing the source code

Stack is introduced in front into and out of the new, and the Queue FIFO is

1, Queue structure

public interface Queue<E> extends Collection<E> {
   
    boolean add(E e);
   
    boolean offer(E e);

    E remove();

    E poll();

    E element();

    E peek();
}

  Queue is an interface.

 

2, PriorityQueue source code analysis

PriorityQueue is a priority queue, the difference between the queue and FIFO are: each priority queue elements are a team of the highest priority elements . How priority to determine which elements of it? jdk heap using this data structure, through the heap so that the smallest per queue always dequeued element, the comparison element size specified by Compareator, corresponding to the priority.

 

3. What is the heap and binary heaps?

1) the value of a stack node is always greater than or not less than that of its parent node

2) heap always a complete tree

Heap scene has a binary heap, Fibonacci heap and so on. The PriorityQueue is a binary heap.

Binary heap is a special stack, binary heap is a complete binary tree or nearly complete binary tree. There are two binary heap: maximum and minimum heap heap

Max heap: key parent node is always greater than or equal to any key of a child node

Minimum stack: the key of the parent node is always less than or equal to any key of a child node

Legend binary heap

 

 The figure is a complete binary tree (binary heap), characterized by: prior to the n-th layer depth is filled, does not start to fill the depth of the n + 1 layer, and the element is inserted is filled from left to right.

Based on this feature, binary heap and can be represented by an array instead of a linked list. We look at the following figure shows an array binary heap

 

 For the n-element array of any element, on the basis binary heap array while its left child 2n + 1 position on the right child of the 2n + 2 position of its parent node in the (n-1) / 2 , while the root node is a position on a 0.

 

4, PriorityQueue data structure, the stack is

public class PriorityQueue<E> extends AbstractQueue<E>
    implements java.io.Serializable {

    // default capacity is 11
    private static final int DEFAULT_INITIAL_CAPACITY = 11;

    // use an array to store the elements
    transient Object[] queue; // non-private to simplify nested class access

    // queue element size 
    private int size = 0;
    // achieve priority queue by the comparator
    private final Comparator<? super E> comparator;
}

  

5, the constructor

We look at the main constructor

public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
    
	if (initialCapacity < 1)
	    throw new IllegalArgumentException();
	this.queue = new Object[initialCapacity];
    	this.comparator = comparator;

}

  

6, add the principle of a binary heap

Binary heap features:

1) the parent node is always less than or equal to any key a key child nodes.

2) based on the binary heap array implemented, for the array of n in any element of the element, its left child 2n + 1 position, the right child 2n + 2 position, its parent node in the (n-1) / 2, while the root node is a position on a 0.

To maintain this characteristic, a binary heap when adding elements, requires a "move up" operation, as shown in FIG.

 

 

7, the source added element analytical

    // add an element
    public boolean add(E e) {
        return offer(e);
    }

    
    public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
	// modified version +1
        modCount++;
	// record the current number of queue elements
        int i = size;
	// if the current number of elements in the queue greater than or equal to the length of the underlying array, expansion is performed
        if (i >= queue.length)
            grow(i + 1);
	// number of elements +1
        size = i + 1;
	// If no element in the queue, then added directly to the root element e
        if (i == 0)
            Queue [0] = e;
	// else calls siftUp method to add elements to the end, shift judgment on
        else
            siftUp(i, e);
        return true;
    }

  

1) operating expansion

    private void grow(int minCapacity) {
        int oldCapacity = queue.length;
        // If the current queue is less than 64, the expansion to 2 times, or 1.5 times expansion
        int newCapacity = oldCapacity + ((oldCapacity < 64) ?
                                         (oldCapacity + 2) :
                                         (oldCapacity >> 1));
        // If the expansion is beyond the scope of int, then newCapacity assigned Integer.Max_VALUE
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
	// array copy for expansion
        queue = Arrays.copyOf(queue, newCapacity);
    }

  

Shifting operation 2)

    Move //, x represents a new insert elements, k is the element in the inserted position of the new array
    private void siftUp(int k, E x) {
	// The comparator is empty, select a different method of operation of the shift
        if (comparator != null)
            siftUpUsingComparator(k, x);
        else
            siftUpComparable(k, x);
    }

    // shifting operation of the comparator is empty, this method is invoked on
    private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
	// k> 0 indicates the case where the determination of k is not the root, that is, x has a parent element.
        while (k > 0) {
	    // parent element x calculated position (n-1) / 2 
            int parent = (k - 1) >>> 1;
	    // remove the parent element x e
            Object e = queue[parent];
	    // If a new element is greater than its parent element E k, you do not need to "move", out of the end of cycle
            if (key.compareTo((E) e) >= 0)
                break;
	    // x smaller than the parent element, we need to "move on"
	    // x switching elements and the position of the parent node e
            Queue [k] = E;
	    // k new insertion point element positions of the parent node position for the next cycle
            k = parent;

        }
	After assignment to find a suitable location k // add element x
        queue[k] = key;
    }

  Summary: "Move Up" binary heap operations primarily will keep the new elements, and parent elements to compare, than the parent node is a small shift. Move the parent node and then compare, until the root node.

 

8, binary heap principle deleted

Corresponding to the binary heap dequeue operation is to delete the root element, which is the smallest element, is moved to find a replacement position of the root, for the element is removed, it is the "down"

 

 

 

 

Combined with the above illustration, let's explain binary heap process of the team:
     1. The element 8 to identify the tail, and delete it at the tail position (FIG. 2);
     2. The element 8 to the tail root of a youngest child element 3 to be large, so that the down element 1, swap positions 1 and 3 (FIG. 3);
     3. At this time, the tail element and then the element 8 than most children of 1 to 4 large, a continue down, the exchange position (FIG. 4) 1 and 4;
     4. At this time, the root element and the element ratio of 8 1 9 youngest child is smaller, no down directly assigned to the root element 8 in this case the position of the elements 1, 1 are covered with the equivalent of deleted (FIG. 5), the end .

 

Reference: https://www.cnblogs.com/linghu-java/p/9467805.html

 

Guess you like

Origin www.cnblogs.com/linlf03/p/12634297.html