Priority queue and heap sort

Priority Queue

definition

Many applications to be processed ordered many elements, but does not necessarily require all of them ordered; or they will not require a sort, in many cases we will deal with the key elements of the current maximum and then gather more elements, a highest priority in the event of handling the largest element, or a priority assigned to each application, and always under treatment.

In this case, an appropriate data structure should support two modes of operation: Remove the largest element, insert the element. This data structure is called a priority queue. Priority queue and queue and use similar stacks. By inserting an element one by one and then delete the smallest element, we can use the priority queue implement sorting algorithms - heap sort.

 

API

We elements must be operated implements the Comparable interface.

MaxPQ (): create a priority queue

MaxPQ (): Create an initial capacity of max priority queue.

MaxPQ (Key [] a) create a priority queue with a array of elements. ,

void insert (Key v) inserting an element.

Key max () returns the largest element in the priority queue

Key delMax () delete the largest element in the priority queue.

 

achieve

Heap Definition

Binary heap data structure can well achieve the basic operation of a priority queue, in binary heap array values, each element must be ensured at the other two positions. Accordingly, the position of these elements is greater than at least equal to the array but also the other two elements, these elements will be drawn into a binary tree, as shown in

 

Ordered stack: when a binary tree of each node is greater than its child nodes is equal to two.

 

Binary heap (hereinafter referred to simply stack) represents

We could represent linked list, so that each node must maintain three reference (a pointer to the parent node, pointing to two children nodes). However, if we use a very simple binary tree (above), we only need to complete the array, in particular a binary tree node into the array hierarchical order, the root node 1 (the array index position 0 No need to). Then in a stack position of the parent node of node K is K / 2, left and right child nodes are 2K, 2K + 1.

 

Heap algorithm

Let N represent a size of the stack, pq [0] without using an array of length pq [] N + 1 is. We need the private helper function to compare and exchange position is as follows

 

private boolean less(int i,int j)
{return pq[i].compareTo(pq[j])<0;
}

private void exch(int i,int j)
{
Key key=pq[i];
pq[i]=pq[j];
pq[j]=key;
}

In the ordering process, we will encounter both cases, the priority of the rise of a node, such as a low bulk adding a new element that we need to restore order from the bottom, the priority of a drop node, For example, the root node is replaced with a priority of smaller elements we need to restore order from top to bottom,

 

Recovery order from the bottom (float)

If the heap ordered state because a node becomes larger than its parent large is broken, then we need to exchange it and parent to repair the heap, the exchange still may be larger than its new parent, we need to continue the exchange until it encounters a larger than its parent or reach the root node.

Code:

 

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

From top to bottom to restore order (sinking)

If the heap ordered state because a node becomes greater than its two children, or one in which little is broken, then we need to exchange it and the larger of the two sub-nodes to repair the heap, the exchange may still occur the case described above, the exchange continues until its two child nodes or smaller than it reaches the bottom of the stack.

Code

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;
exch(k,j);
k=j;

}
}

插入元素

我们将新元素放到数组的末尾,增加堆的大小并让这个元素上浮到合适的位置。

 

删除最大元素

我们从数组顶端删除最大元素并将数组的最后一个元素放到顶端,减少堆的大小并将这个元素下沉到合适的位置。

这两种操作如图所示:

完整代码:

 1 public class MaxPQ<Key extends Comparable<Key>> {
 2     private Key pq[];
 3     private int N=0;
 4     public MaxPQ(int max)
 5     {
 6         pq=(Key[])new Comparable[max];
 7     }
 8     
 9     private boolean less(int i,int j)
10     {return pq[i].compareTo(pq[j])<0;
11     }
12 
13     private void exch(int i,int j)
14     {
15        Key key=pq[i];
16        pq[i]=pq[j];
17        pq[j]=key;
18     }
19     
20     private void swim(int k)
21     {
22         while(k>1&&less(k/2,k))
23         {
24             exch(k/2,k);
25             k=k/2;
26         }
27     }
28     
29     private void sink(int k)
30     {
31         while(2*k<=N)
32         {
33             int j=2*k;
34             if(j<N&&less(j,j+1)) j++;
35             if(!less(k,j)) break;
36             exch(k,j);
37             k=j;
38                 
39         }
40     }
41     
42     public boolean isEmpty()
43     {
44         return N==0;
45     }
46     
47     public int size()
48     {
49         return N;
50     }
51     
52     public void insert(Key key)
53     {
54         pq[++N]=key;
55         swim(N);
56     }
57     
58     public Key delMax()
59     {
60         Key max=pq[1];
61         exch(1,N--);//传递的参数为N,当函数执行完后再执行N--;
62         pq[N+1]=null;
63         sink(1);
64         return max;
65         
66     }
67 
68 
69 }
View Code

 

注意:本代码没有考虑数组越界问题,所有操作都是理想的,不会发生异常

 

堆排序

 对于上面的优先队列,只要我们改变一下less()函数的判断条件,就可以就可以将他变为一个删除最小元素的优先队列。

堆排序分为两个阶段,在堆的构造阶段,我们将原始数组重新组织安排到一个堆中,然后在下沉排序阶段,我们从堆中按照递减顺序取出所有元素并得到排序结果,为了排序的需要,我们将直接使用swim()和sink()方法。

 

堆的构造

关于如何构造堆,我们有两种方式

(1)采用swim()方法,从左往右扫描数组,这样可以保证指针左侧的元素都是堆有序的,这种方式类似于创建一个空堆,然后不断调用insert()方法。

(2)采用sink()方法,从右往左扫描数组,对于一个给定的数组,每一个元素都可以看成是一个已经排好的堆,如果一个结点的两个子节点都已经是堆了,那么在该节点上调用sink()方法也能将他们变成堆。使用这种方法我们只需要扫描一办的数组

 

代码实现

 

 1 public class Heap {
 2     private Heap() { }
 3 
 4   
 5     public static void sort(Comparable[] pq) {
 6         int n = pq.length;
 7         for (int k = n/2; k >= 1; k--)
 8             sink(pq, k, n);
 9         while (n > 1) {
10             exch(pq, 1, n--);
11             sink(pq, 1, n);
12         }
13     }
14 
15   
16 
17     private static void sink(Comparable[] pq, int k, int n) {
18         while (2*k <= n) {
19             int j = 2*k;
20             if (j < n && less(pq, j, j+1)) j++;
21             if (!less(pq, k, j)) break;
22             exch(pq, k, j);
23             k = j;
24         }
25     }
26 
27  
28     private static boolean less(Comparable[] pq, int i, int j) {
29         return pq[i-1].compareTo(pq[j-1]) < 0;
30     }
31 
32     private static void exch(Object[] pq, int i, int j) {
33         Object swap = pq[i-1];
34         pq[i-1] = pq[j-1];
35         pq[j-1] = swap;
36     }
37 
38 
39  }
View Code

下沉排序:

我们将堆中最大的元素删除,然后放入堆缩小后空出的位置

算法行为:

 

Guess you like

Origin www.cnblogs.com/lls101/p/11230379.html