And priority queue (binary) stack

  Data structures and algorithms book books (including Introduction to Algorithms , algorithm design ) generally priority queue (Priority Queue) speaks with the stack (Heap) on, talk about this particular stack data structure Introduction to Algorithms, say after two stack application heap sort and priority queues. Algorithm design book talk about the priority queue is what kind of data structure, what is the nature of why this priority queue data structure, then speaks to realize what kind of priority queue requirements, and these requirements arrays (Array) and the list ( Linked List) are not met, so we need to design a new data structure to meet these requirements, and that is the heap. Personally I prefer this order on algorithm design book.

  Some specific algorithm, requiring only a fraction information data, without the need for all the information, this time in order to enhance the efficiency of the algorithm, it may be necessary to design a specific data structure, this particular data structure retained only the algorithm needed that part of the information, and give up the rest of the information, give up this part of the information exchange to enhance the efficiency, which is exactly what we need. For example visual point, an array of this data structure, you know the value of each element (element) array, which is equivalent to know all the information, but such data stack structure, such as the minimum heap, you know the top of the stack What elements, and other elements of the heap you do not know, you just know the equivalent of partial information. If an algorithm, you only care about the minimum number of data, without regard to the specific values for each data, it fails to meet the minimum heap your needs. For efficiency, for an array of size n, minimum required to traverse the entire array, time \ (\ mathcal {O} (n) \) , and the top of the stack, i.e. the stack elements of the minimum min-heap data, only \ (\ mathcal {O} ( 1) \) time.

  In [to be] filled pit stable matching problem, the need to maintain a set S, the operation of the set S include: insert elements, remove elements, visit the highest priority (priority own definition) elements, and to this end is the priority queue Designed.

Priority Queue

definition

Priority queue is a data structure that maintains a set S, each element \ (v \ in S \) has a corresponding key \ (key (v) \) indicating the priority, the key element corresponding to the small high priority. Priority queue element support is inserted, deleted elements, the minimum access key element \ (^ {[1]} \) .

  A typical application is to simplify the priority queue scheduling computer process (process scheduling) problem, each process has a priority. Each process is not generated in order of priority, we maintain a set of processes, every time we choose a set in the highest priority process to run, and remove the process from the collection, and we will go in this collection increase the new process, these positive features correspond to priority queues.

Expected complexity

  So we expect the size of the priority queue n times the number of degrees of complexity to achieve it?
  We know that the lower bound on the time complexity of sorting algorithms comparison is \ (\ mathcal {O} (the n-\ the n-log) \) , from this lower bound, we can conclude that each priority queue insert elements, remove elements, visit the minimum desired time complexity of key elements. Suppose we have an array of size n, we turn to each array element are added to the priority queue, then the queue priority elements are taken out of order, then taken out, there were already elements of the order, we realized the a sorted array. The above operation there are n insertions, n times taken, n times the delete operation, it can be seen, the time complexity of these basic operations of a priority queue (presumably) lower bound should be \ (\ mathcal {O} ( \ log n) \) . But in practice, due to the implementation of a priority queue is not the same, the operation time is substantially different from the lower bound \ (^ {[3]} \) , but for this sort of problem in terms of the array, the method priority queue to sort (actually hEAPSORT) is lower bound time \ (\ mathcal {O} (n-\ log n-) \) .

stack

Arrays and linked lists limitations

  For an array or linked list, the basic operation can achieve \ (\ mathcal {O} (\ log n-) \) ?
  the answer is negative. In the process of scheduling example, if we follow the order of priority of the process in different positions, the access time and delete operations can be \ (\ mathcal {O} (. 1) \) . However, the insertion operation can not meet the requirements for the array, finding the insertion location can be found to be achieved by binary \ (\ mathcal {O} ( \ log n) \) time, but time is inserted element \ (\ {O} mathcal (n-) \) , and for the list, the time element is inserted \ (\ mathcal {O} (. 1) \) , but we need to find the location of the insertion \ (\ mathcal {O} ( n) \) time. In summary, arrays and linked lists do not meet our requirements, need to design new data structures - stack.

definition

  There are many types heap, binary heap, two heaps, Fibonacci heap, etc., here talking about the binary heap. Binary heap is a balanced binary tree can be considered as approximate or complete binary tree, the difference between the depth of the left and right subtrees of any node in the balanced binary tree of not more than 1, the same depth of the complete binary tree leaf node, the degree of internal node (Degree, children the number of nodes) of the same.


Complete binary tree

1 complete binary tree

The figure is a schematic view of a stack, but also a balanced binary tree, it can be seen, the stack It is called a complete binary tree approximate because not all of the internal nodes are the same.

Heap (balanced binary tree)

FIG stack (balanced binary tree)

  Stack has a property called heap Order , for purposes of the minimum heap, i.e. any node key in the tree of the key to the key-value greater than or equal key of its parent node, the maximum heap and vice versa. Figure 2 shows the minimum heap.
  Usually array to store the stack, the stack shown in FIG. 2, the minimum may be stored as shown in Figure 3:

Array representation of the heap

Figure 3 represents an array of the stack

Wherein, the array subscripts A from 1 to N, N being the size of the heap, A [1] is the root node, A [2] is a left child of the root node of the child, A [. 3] is the right child of the root node child . Indeed, for any node, if its position in the array is i, then its left child node locations child \ (left \ _child (I) = 2i \) , the right child node locations child \ (right \ _child = . 1 + 2i \) (if there is a position) of its parent \ (parent (i) = \ lfloor i \ rfloor \) , \ (\ lfloor i \ rfloor \) represents rounding down of i. Arrow in FIG. 3 about the child from the parent node pointing to child nodes, respectively.

Implemented by heap priority queue

Basic Operations

  We review the basic operation of the priority queue, and see with minimum heap array representation of how to achieve these operations.

  • Access to the highest priority (smallest key key) elements

  A heap order to know the nature of the stack, A [1] that is the key element is the smallest, so only need to return to A [1] the value.

  • Insert elements

  We maintain a variable \ (length \) represents the size of the heap, each element is added to the heap when the \ (length \) plus 1, then the value assigned to the array elements in A \ (length \) position.

  • Removing elements

  Many applications priority queue is usually only removes the element after visiting the highest priority elements. For the array A, the only need A [1] can be deleted, practical implementation, we will be A [length] assigned to A [1], then the length minus one.

  We need to note that, insert elements and remove elements will change the value of the array, and then change the array can indicate whether a heap of it? The answer is not necessarily, because the change is not necessarily in line with the value of the array heap order, so we need to do something to maintain the heap order nature of the heap.

Maintenance nature heap

  Heap order to maintain the maximum heap properties for example, after inserting the element, A [length] A value may be greater than the value of [parent (length)], it is necessary to adjust the A [length] values to the appropriate location. Heap_increase_key needed to achieve the insertion operation, the pseudo code \ (^ {[2]} \) as follows:

heap_increase_key(A, i, key){
    A[i] = key
    while(i > 1 && A[parent(i)] < A[i]) {
        exchange A[i] and A[parent(i)]
        i = parent(i)
    }
}

  Simply put, when A [i] is greater than the value of its parent node, the exchange of both, until the A [i] is less than or equal to the value of the parent node of the root node has been reached. 4 is a schematic heap_increase_key (A, 9, 15) of:


heap_increase_key(A, 9, 15)

图4 heap_increase_key(A, 9, 15)

  Similarly, after removing elements, A [length] value assigned to A [1], at a time when A [1] may be less than A [left_child (1)] or A [right_child (1)], it is necessary to A [ value 1] is adjusted to the appropriate position. Using the function to achieve max_heapify delete operation, the input array A and the subscript i, we assume that A [i] is the value of the unique nature of the violation of the stack, call max_heapify (A, i) so that A [i] is the maximum value of the stack "by level down ", so as to maintain the nature of the heap. Pseudocode \ (^ {[2]} \) as follows:

max_heapify(A, i){
    l = left_child(i)
    r = right_child(i)
    largest = i
    if(l <= length && A[l] > A[i])
        largest = l
    if(r <= length && A[r] > A[largest])
        largest = r
    if(largest != i){
        exchange A[i] and A[largest]
        max_heapify(A, largest);
    }
}

  Simply put, the left and right child node and a child node i, the largest node Largest selected key, if not Largest i, A [i] and A [largest] is the value of the exchange, which at this time is three nodes in line with the nature of the heap, but a [largest] may violate the heap property, so we recursive call max_heapify (a, largest) function. FIG 5 is a max_heapify (A, 2) of FIG.


max_heapify(A, 2)

图5 max_heapify(A, 2)

  heap_increase_key and along a path tree are max_heapify, walked root from the leaf node in the worst case (max_heapify come leaf node from the root node), the time complexity is \ (\ mathcal {O} ( \ log n ) \) .

  Similar heap_increase_key and max_heapify, not difficult to get heap_decrese_key and min_heapify, so we will give priority to insert and delete elements operating elements complete the following queue:

  • Insert elements

  We maintain a variable \ (length \) represents the size of the heap, each element is added to the heap when the \ (length \) plus 1, then INT_MIN assigned to A [length], and then call once heap_decrease_key (A , length, key).

  • Removing elements

  Many applications priority queue is usually only removes the element after visiting the highest priority elements. For the array A, the only need A [1] can be deleted, practical implementation, we will be A [length] assigned to A [1], then the length minus one. Then call once min_heapify (A, 1).

Time priority queue basic operation complexity

operating time complexity
Insert elements \(\mathcal{O}(\log n)\)
Removing elements \(\mathcal{O}(\log n)\)
Access to the highest priority elements \(\mathcal{O}(1)\)

  

Implementation

  The basic operation of the above given minimum heap priority queue based on the following pseudo-code:

  • Access the smallest key elements
heap_minimum(A){
    return A[1]
}
  • Insert
min_heap_insert(key){
    length = length + 1
    A[length] = INT_MAX
    heap_decrease_key(length, key)
}
  • Access key to delete the element after the largest element
heap_extract_min(A){
    min = A[1]
    A[1] = A[length]
    length = length - 1
    min_heapify(A, 1)
    return min
}

example

Exercise classes algorithms: Dynamic Median

  A link failure to prevent cross-sectional diagram put it:


Dynamic Median

图6 Dynamic Median

Algorithm thinking

  Respectively, to achieve a maximum heap, a minimum heap, the heap is the largest of all the elements of any element less than or equal to the minimum heap. Minimum maximum heap size of the heap by no more than 1, when the minimum size of the heap than a large maximum heap size, the minimum median stack top of the stack of elements, the remaining cases, the top of the stack elements are median maximum stack (consistent with the subject requirements). When inserting a new element, if the element is larger than the median value of the stack is inserted to a minimum, and vice versa, is inserted to the maximum stack, while maintaining two heap size should not differ by more than 1.

Write your own heap implementation

  23596kB, 1084ms

  Comparing the code length, because the function name corresponding to the pseudo-code above, separate minimum maximum heap stack.

#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <algorithm>
#include <iostream>

#define parent(i) (int)std::floor(i/2)
#define left(i) i * 2
#define right(i) i * 2 + 1

int A[5005], B[5005];//分别存储最大堆、最小堆
int max_heap_size, min_heap_size;

void exchange(int* array, int i, int j) {
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
}

//最大堆
void heap_increase_key(int i, int key) {
    if (key < A[i])
        printf("error: new key is smaller than current key.");
    A[i] = key;
    while (i > 1 && A[parent(i)] < A[i])
    {
        exchange(A, i, parent(i));
        i = parent(i);
    }
}

void max_heap_insert(int key) {
    max_heap_size++;
    A[max_heap_size] = INT_MIN;
    heap_increase_key(max_heap_size, key);
}

int heap_maximum(void) {
    return A[1];
}

void max_heapify(int i) {
    int l = left(i), r = right(i);
    int largest = i;
    if (l <= max_heap_size && A[l] > A[i])
        largest = l;
    if (r <= max_heap_size && A[r] > A[largest])
        largest = r;
    if (largest != i) {
        exchange(A, i, largest);
        max_heapify(largest);
    }
}

int heap_extract_max(void) {
    int max = A[1];
    A[1] = A[max_heap_size];
    max_heap_size--;
    max_heapify(1);
    return max;
}

//最小堆
void heap_decrease_key(int i, int key) {
    if (key > B[i])
        printf("error: new key is bigger than current key.");
    B[i] = key;
    while (i > 1 && B[parent(i)] > B[i])
    {
        exchange(B, i, parent(i));
        i = parent(i);
    }
}

void min_heap_insert(int key) {
    min_heap_size++;
    B[min_heap_size] = INT_MAX;
    heap_decrease_key(min_heap_size, key);
}

int heap_minimum(void) {
    return B[1];
}

void min_heapify(int i) {
    int l = left(i), r = right(i);
    int smallest = i;
    if (l <= min_heap_size && B[l] < B[i])
        smallest = l;
    if (r <= min_heap_size && B[r] < B[smallest])
        smallest = r;
    if (smallest != i) {
        exchange(B, i, smallest);
        min_heapify(smallest);
    }
}

int heap_extract_min(void) {
    int min = B[1];
    B[1] = B[min_heap_size];
    min_heap_size--;
    min_heapify(1);
    return min;
}

int quary(void) {
    if (min_heap_size == max_heap_size + 1)
        return heap_minimum();
    else//max_heap_size = min_heap_size + 1或size相等
        return heap_maximum();
}

void insert(int x) {
    if ((!min_heap_size) && (!max_heap_size))//第一个数据
        max_heap_insert(x);
    else {
        int median = quary();
        if (x < median) {
            max_heap_insert(x);
            if (max_heap_size == min_heap_size + 2)//保持最大堆和最小堆的size相差不超过1
                min_heap_insert(heap_extract_max());
        }           
        else {
            min_heap_insert(x);
            if (min_heap_size == max_heap_size + 2)
                max_heap_insert(heap_extract_min());
        }           
    }

}

void del(void) {//del操作后,最大堆最小堆的size相差不超过1的性质不变
    if (min_heap_size == max_heap_size + 1)
        heap_extract_min();
    else
        heap_extract_max();
}
int main() {
    int t, n, x;
    char op;
    scanf("%d", &t);
    while (t--) {
        max_heap_size = 0;
        min_heap_size = 0;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf(" %c", &op);
            if (op == 'I') {
                scanf("%d", &x);
                insert(x);
            }
            else if (op == 'Q')
                printf("%d\n", quary());
            else
                del();
        }
    }
    return 0;
}

Library routines

23724kB, 1288ms

#include <stdio.h>
#include <queue>
#include <functional>

std::priority_queue<int> max_heap;
std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap;

int quary(void) {
    if (min_heap.size() == max_heap.size() + 1)
        return min_heap.top();
    else//max_heap_size = min_heap_size + 1或size相等
        return max_heap.top();
}

void insert(int x) {
    if (min_heap.empty() && max_heap.empty())
        max_heap.push(x);
    else {
        int median = quary();
        if (x < median) {
            max_heap.push(x);
            if (max_heap.size() == min_heap.size() + 2) {
                min_heap.push(max_heap.top());
                max_heap.pop();
            }               
        }
        else {
            min_heap.push(x);
            if (min_heap.size() == max_heap.size() + 2) {
                max_heap.push(min_heap.top());
                min_heap.pop();
            }               
        }
    }
}

void del(void) {
    if (min_heap.size() == max_heap.size() + 1)
        min_heap.pop();
    else
        max_heap.pop();
}
int main() {
    int t, n, x;
    char op;
    scanf("%d", &t);
    while (t--) {
        while (!min_heap.empty())
            min_heap.pop();
        while (!max_heap.empty())
            max_heap.pop();
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf(" %c", &op);
            if (op == 'I') {
                scanf("%d", &x);
                insert(x);
            }
            else if (op == 'Q')
                printf("%d\n", quary());
            else
                del();
        }
    }
    return 0;
}

reference:

[1] algorithm design
[2] Introduction to Algorithms
[. 3] Algorithm Design Lecture the slides: binary and Binomial Heaps

Guess you like

Origin www.cnblogs.com/wtyuan/p/12075500.html