Algorithm - Priority Queue

Many applications need to deal with ordered elements, but not necessarily all of them, or all at once. In many cases, we will collect some elements, process the element with the largest current key value, then collect more elements, and then process the element with the largest current key value, and so on. For example, you might have a computer that can run multiple applications at the same time. This is achieved by assigning a priority to each application's events and always processing the next highest priority event. For example, most cell phones will assign a higher priority to incoming calls than gaming programs.

In layman's terms , when the collection of elements will never stop, which is equivalent to an infinite number of elements, then we will never finish comparing all the elements, and we may only use the ten largest elements, so we only need to put the new entry. The elements of the queue are compared with these ten elements, and the smallest one can be removed.

In this case, a suitable data structure should support two operations, deleting the largest element and inserting an element . This data type is called a finite queue.

Priority queue is an abstract data type with the following API (Key is generic):

 

public class MaxPQ<Key extends Comparable<Key>>
MaxPQ() creates a priority queue       
    MaxPQ(int max) creates a priority queue with an initial capacity of max
  MaxPQ(Key[] a) Create a priority queue with the elements in a[]
void insert(key v) inserts an element into the priority queue
Key max() returns the largest element
  Key dekMax() removes and returns the largest element
boolean isEmpty() returns whether the queue is empty
int size() returns the number of elements in the priority queue

 

 

A use case for a priority queue:

public class TopM{
	public static void main(String []args) {
		//打印输入流中的最大的M行
		int M=Integer.parseInt(args[0]);
		MinPQ<Transaction> pq=new MinPQ<Transaction>(M+1);
		while(StdIn.hasNextLine()) {
			//为下一行输入创建一个元素并放入优先队列中
			pq.insert(new Transaction(StdIn.readLine));
			if(pq.size()>M) {
				pq.delMin();//如果优先队列中存在M+1个元素则删除其中最小的元素
			}//最大的M的元素都在优先队列中
			Stack<Transaction> stack=new Stack<Transaction>();
			while(!pq,isEmpty) stack.push(pq.delMin());
			for(Transaction t:stack)StdOut.println(t);
		}
	}
}

Analysis : First obtain an integer M from the input stream, and save the M largest elements, then continuously obtain new elements from the input stream, compare with the old M elements, delete the smallest one of them, and ensure that MinPQ always exists. The largest M elements.

Primary implementation :

Array implementation (unordered): When deleting, exchange the element to be deleted with the boundary element, and then delete it;

Array implementation (ordered): arrange in order, such as deleting the largest, delete the boundary value forever;

List notation: You can use the code of the linked list-based push station as a basis, arrange in reverse order, and pop() to delete.

Comparison : The biggest difference between implementing stacks and queues and implementing priority queues is the performance requirements. For stacks and queues, our implementation is able to complete all operations in a constant time implementation; while for priority queues, in all the preliminary implementations we just discussed, one of the two operations, inserting an element and removing the largest element, is in the worst case It takes linear time to complete, but a heap-based implementation of the data structure is guaranteed to execute both operations faster ( logarithmically ).

The definition of heap : In the array of binary tree, each element must be guaranteed to be greater than or equal to the other two elements in a specific position. In a tree, i.e. each node is larger than its two cotyledons.

Representation of a binary heap : if a linked list is used, each element requires three pointers; but if a complete binary tree is used, it can be easily represented by an array. The complete binary tree is stored in an array, the root node is stored in a[1], and the other nodes are stored in order from top to bottom and from left to right. It should be noted that a[0] does not store node information.

The position of the parent node of the node at position K is (k/2) rounded down, and the positions of its two child nodes are 2K and 2K+1 respectively;

The height of a complete binary tree of size N is (lgN) rounded down.

Heap algorithm :

The operation of the heap first makes some simple changes to break the state of the heap, and then traverses the heap and restores the state of the heap as required. We call this process the ordering of the heap.

private boolean less(int i,int j){     //比较i和j的值
    return pq[i].compareTo(pq[j])<0;)
}
private void exch(int i,int j){
    Key t=pq[i];
    pq[i]=pq[j];
    pq[j]=t;
}

Bottom-up pair ordering (up-swim): swap it with its parent to fix the heap.

private void swim(int k){
    while(k>1&&less(k/2,k))
{
    exch(k/2,k);
    k=k/2;
}
}

Top-to-bottom heap ordered change (sink): swap it and the larger of its two children to swap the recovery heap.

private void sink(int k){
    while(2*k<=N){
      int j=2*k;
      if(j<N&&less(j,j+1))j++;
      if(!less(k,j))break;
      each(k,j);
      k=j;
}
}

Performance : For a finite heap-based queue with N elements, inserting an element requires no more than (lgN+1) comparisons, and removing the largest element requires no more than 2lgN comparisons. can be done in logarithmic time.

Improvement : ① Multi-fork heap

            ②Adjust the size of the array

            ③ The immutability of elements

            ④Index priority sequence

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325310664&siteId=291194637