📜  使用二进制堆的优先级队列

📅  最后修改于: 2021-05-18 00:23:04             🧑  作者: Mango

Priority Queue是具有以下属性的队列扩展:

  1. 每个项目都有与之关联的优先级。
  2. 具有高优先级的元素在具有低优先级的元素之前先出队。
  3. 如果两个元素具有相同的优先级,则将根据它们在队列中的顺序为其提供服务。

二进制堆是具有以下属性的二进制树:

  1. 这是一棵完整的树。 Binary Heap的此属性使它们适合存储在数组中。
  2. 二进制堆是“最小堆”或“最大堆”
  3. 最小二进制堆中,在二进制堆中存在的所有密钥中,根目录中的密钥必须最小。对于二叉树中的所有节点,相同的属性必须递归地为true。
  4. 同样,在“最大二进制堆”中,在二进制堆中存在的所有密钥中,根目录中的密钥必须最大。对于二叉树中的所有节点,相同的属性必须递归地为true。

二元堆操作

  • insert(p):插入优先级为p的新元素。
  • extractMax():提取具有最高优先级的元素。
  • remove(i):删除由迭代器i指向的元素。
  • getMax():返回具有最高优先级的元素。
  • changePriority(i,p):i指向的元素的优先级更改为p

二进制最大堆的示例

  • 假设下面是给定的Binary Heap,它遵循Binary Max Heap的所有属性。

  • 现在,需要在上面的堆中插入值为32的节点要插入元素,请将新元素附加到任何叶子。例如,可以将优先级为32的节点添加到节点11的叶中。但这违反了堆属性。为了保持堆属性,请向上移动新节点32

  • 上移操作将正确放置32的节点移到正确的位置:将错误放置的节点与其父节点交换,直到满足heap属性为止。例如:由于节点11小于节点32,因此交换节点11和节点32 。然后,交换节点14和节点32 。最后,交换节点31和节点32

  • ExtractMax:最大值存储在树的根目录中。但是树的根不能直接删除。首先,将其替换为任何一片叶子,然后将其移除。例如:要删除节点45 ,首先将其替换为节点11 。但这违反了heap属性,因此请向下移动替换的节点。为此,请使用下移操作。

  • ShiftDown操作:用较大的子项交换放置不正确的节点,直到满足heap属性。例如:节点11与节点32交换,然后与节点31交换,最后与节点14交换。

  • ChangePriority:让更改后的元素根据其优先级是降低还是增加而上下移动。例如:将节点11的优先级更改为35 ,由于此更改,节点必须上移节点才能维护堆属性。
  • 删除:要删除元素,请将其优先级更改为大于当前最大值的值,然后将其上移,然后使用Extract max进行提取。使用getMax查找当前最大值。
  • GetMax:最大值存储在树的根目录中。要获得maxmax,只需在树的根目录处返回该值即可。

二进制堆的数组表示

由于以完整的二叉树形式维护堆,因此,可以以数组形式表示堆。为了保持树的完整和浅浅,在插入新元素时将其插入到最后一级的最左边的空白位置,即数组的末尾。同样,在提取最大值时,将根替换为最后一级的最后一片叶子,即数组的最后一个元素。下面是相同的插图:

下面是使用Binary Heap实现Priority Queue的程序:

C++
// C++ code to implement priority-queue
// using array implementation of
// binary heap
 
#include 
using namespace std;
 
int H[50];
int size = -1;
 
// Function to return the index of the
// parent node of a given node
int parent(int i)
{
 
    return (i - 1) / 2;
}
 
// Function to return the index of the
// left child of the given node
int leftChild(int i)
{
 
    return ((2 * i) + 1);
}
 
// Function to return the index of the
// right child of the given node
int rightChild(int i)
{
 
    return ((2 * i) + 2);
}
 
// Function to shift up the node in order
// to maintain the heap property
void shiftUp(int i)
{
    while (i > 0 && H[parent(i)] < H[i]) {
 
        // Swap parent and current node
        swap(H[parent(i)], H[i]);
 
        // Update i to parent of i
        i = parent(i);
    }
}
 
// Function to shift down the node in
// order to maintain the heap property
void shiftDown(int i)
{
    int maxIndex = i;
 
    // Left Child
    int l = leftChild(i);
 
    if (l <= size && H[l] > H[maxIndex]) {
        maxIndex = l;
    }
 
    // Right Child
    int r = rightChild(i);
 
    if (r <= size && H[r] > H[maxIndex]) {
        maxIndex = r;
    }
 
    // If i not same as maxIndex
    if (i != maxIndex) {
        swap(H[i], H[maxIndex]);
        shiftDown(maxIndex);
    }
}
 
// Function to insert a new element
// in the Binary Heap
void insert(int p)
{
    size = size + 1;
    H[size] = p;
 
    // Shift Up to maintain heap property
    shiftUp(size);
}
 
// Function to extract the element with
// maximum priority
int extractMax()
{
    int result = H[0];
 
    // Replace the value at the root
    // with the last leaf
    H[0] = H[size];
    size = size - 1;
 
    // Shift down the replaced element
    // to maintain the heap property
    shiftDown(0);
    return result;
}
 
// Function to change the priority
// of an element
void changePriority(int i, int p)
{
    int oldp = H[i];
    H[i] = p;
 
    if (p > oldp) {
        shiftUp(i);
    }
    else {
        shiftDown(i);
    }
}
 
// Function to get value of the current
// maximum element
int getMax()
{
 
    return H[0];
}
 
// Function to remove the element
// located at given index
void remove(int i)
{
    H[i] = getMax() + 1;
 
    // Shift the node to the root
    // of the heap
    shiftUp(i);
 
    // Extract the node
    extractMax();
}
 
// Driver Code
int main()
{
 
    /*         45
            /      \
           31      14
          /  \    /  \
         13  20  7   11
        /  \
       12   7
    Create a priority queue shown in
    example in a binary max heap form.
    Queue will be represented in the
    form of array as:
    45 31 14 13 20 7 11 12 7 */
 
    // Insert the element to the
    // priority queue
    insert(45);
    insert(20);
    insert(14);
    insert(12);
    insert(31);
    insert(7);
    insert(11);
    insert(13);
    insert(7);
 
    int i = 0;
 
    // Priority queue before extracting max
    cout << "Priority Queue : ";
    while (i <= size) {
        cout << H[i] << " ";
        i++;
    }
 
    cout << "\n";
 
    // Node with maximum priority
    cout << "Node with maximum priority : "
         << extractMax() << "\n";
 
    // Priority queue after extracting max
    cout << "Priority queue after "
         << "extracting maximum : ";
    int j = 0;
    while (j <= size) {
        cout << H[j] << " ";
        j++;
    }
 
    cout << "\n";
 
    // Change the priority of element
    // present at index 2 to 49
    changePriority(2, 49);
    cout << "Priority queue after "
         << "priority change : ";
    int k = 0;
    while (k <= size) {
        cout << H[k] << " ";
        k++;
    }
 
    cout << "\n";
 
    // Remove element at index 3
    remove(3);
    cout << "Priority queue after "
         << "removing the element : ";
    int l = 0;
    while (l <= size) {
        cout << H[l] << " ";
        l++;
    }
    return 0;
}


Java
// Java code to implement
// priority-queue using
// array implementation of
// binary heap
import java.util.*;
class GFG{
 
static int []H = new int[50];
static int size = -1;
 
// Function to return the index of the
// parent node of a given node
static int parent(int i)
{
  return (i - 1) / 2;
}
 
// Function to return the index of the
// left child of the given node
static int leftChild(int i)
{
  return ((2 * i) + 1);
}
 
// Function to return the index of the
// right child of the given node
static int rightChild(int i)
{
  return ((2 * i) + 2);
}
 
// Function to shift up the
// node in order to maintain
// the heap property
static void shiftUp(int i)
{
  while (i > 0 &&
         H[parent(i)] < H[i])
  {
    // Swap parent and current node
    swap(parent(i), i);
 
    // Update i to parent of i
    i = parent(i);
  }
}
 
// Function to shift down the node in
// order to maintain the heap property
static void shiftDown(int i)
{
  int maxIndex = i;
 
  // Left Child
  int l = leftChild(i);
 
  if (l <= size &&
      H[l] > H[maxIndex])
  {
    maxIndex = l;
  }
 
  // Right Child
  int r = rightChild(i);
 
  if (r <= size &&
      H[r] > H[maxIndex])
  {
    maxIndex = r;
  }
 
  // If i not same as maxIndex
  if (i != maxIndex)
  {
    swap(i, maxIndex);
    shiftDown(maxIndex);
  }
}
 
// Function to insert a
// new element in
// the Binary Heap
static void insert(int p)
{
  size = size + 1;
  H[size] = p;
 
  // Shift Up to maintain
  // heap property
  shiftUp(size);
}
 
// Function to extract
// the element with
// maximum priority
static int extractMax()
{
  int result = H[0];
 
  // Replace the value
  // at the root with
  // the last leaf
  H[0] = H[size];
  size = size - 1;
 
  // Shift down the replaced
  // element to maintain the
  // heap property
  shiftDown(0);
  return result;
}
 
// Function to change the priority
// of an element
static void changePriority(int i,
                           int p)
{
  int oldp = H[i];
  H[i] = p;
 
  if (p > oldp)
  {
    shiftUp(i);
  }
  else
  {
    shiftDown(i);
  }
}
 
// Function to get value of
// the current maximum element
static int getMax()
{
  return H[0];
}
 
// Function to remove the element
// located at given index
static void remove(int i)
{
  H[i] = getMax() + 1;
 
  // Shift the node to the root
  // of the heap
  shiftUp(i);
 
  // Extract the node
  extractMax();
}
   
static void swap(int i, int j)
{
  int temp= H[i];
  H[i] = H[j];
  H[j] = temp;
}
 
// Driver Code
public static void main(String[] args)
{
 
  /*           45
            /        \
           31      14
          /  \    /  \
         13  20  7   11
        /  \
       12   7
    Create a priority queue shown in
    example in a binary max heap form.
    Queue will be represented in the
    form of array as:
    45 31 14 13 20 7 11 12 7 */
 
  // Insert the element to the
  // priority queue
  insert(45);
  insert(20);
  insert(14);
  insert(12);
  insert(31);
  insert(7);
  insert(11);
  insert(13);
  insert(7);
 
  int i = 0;
 
  // Priority queue before extracting max
  System.out.print("Priority Queue : ");
  while (i <= size)
  {
    System.out.print(H[i] + " ");
    i++;
  }
 
  System.out.print("\n");
 
  // Node with maximum priority
  System.out.print("Node with maximum priority : " +
                    extractMax() + "\n");
 
  // Priority queue after extracting max
  System.out.print("Priority queue after " +
                   "extracting maximum : ");
  int j = 0;
  while (j <= size)
  {
    System.out.print(H[j] + " ");
    j++;
  }
 
  System.out.print("\n");
 
  // Change the priority of element
  // present at index 2 to 49
  changePriority(2, 49);
  System.out.print("Priority queue after " +
                   "priority change : ");
  int k = 0;
  while (k <= size)
  {
    System.out.print(H[k] + " ");
    k++;
  }
 
  System.out.print("\n");
 
  // Remove element at index 3
  remove(3);
  System.out.print("Priority queue after " +
                   "removing the element : ");
  int l = 0;
  while (l <= size)
  {
    System.out.print(H[l] + " ");
    l++;
  }
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 code to implement priority-queue
# using array implementation of
# binary heap
 
H = [0]*50
size = -1
   
# Function to return the index of the
# parent node of a given node
def parent(i) :
 
    return (i - 1) // 2
   
# Function to return the index of the
# left child of the given node
def leftChild(i) :
 
    return ((2 * i) + 1)
   
# Function to return the index of the
# right child of the given node
def rightChild(i) :
 
    return ((2 * i) + 2)
     
# Function to shift up the 
# node in order to maintain 
# the heap property
def shiftUp(i) :
 
    while (i > 0 and H[parent(i)] < H[i]) :
           
        # Swap parent and current node
        swap(parent(i), i)
       
        # Update i to parent of i
        i = parent(i)
         
# Function to shift down the node in
# order to maintain the heap property
def shiftDown(i) :
 
    maxIndex = i
       
    # Left Child
    l = leftChild(i)
       
    if (l <= size and H[l] > H[maxIndex]) :
     
        maxIndex = l
       
    # Right Child
    r = rightChild(i)
       
    if (r <= size and H[r] > H[maxIndex]) :
     
        maxIndex = r
       
    # If i not same as maxIndex
    if (i != maxIndex) :
     
        swap(i, maxIndex)
        shiftDown(maxIndex)
         
# Function to insert a 
# new element in 
# the Binary Heap
def insert(p) :
     
    global size
    size = size + 1
    H[size] = p
       
    # Shift Up to maintain 
    # heap property
    shiftUp(size)
   
# Function to extract 
# the element with
# maximum priority
def extractMax() :
     
    global size
    result = H[0]
       
    # Replace the value 
    # at the root with 
    # the last leaf
    H[0] = H[size]
    size = size - 1
       
    # Shift down the replaced 
    # element to maintain the 
    # heap property
    shiftDown(0)
    return result
   
# Function to change the priority
# of an element
def changePriority(i,p) :
 
    oldp = H[i]
    H[i] = p
       
    if (p > oldp) :
     
        shiftUp(i)
  
    else :
     
        shiftDown(i)
   
# Function to get value of 
# the current maximum element
def getMax() :
  
    return H[0]
   
# Function to remove the element
# located at given index
def Remove(i) :
 
    H[i] = getMax() + 1
       
    # Shift the node to the root
    # of the heap
    shiftUp(i)
       
    # Extract the node
    extractMax()
   
def swap(i, j) :
     
    temp = H[i]
    H[i] = H[j]
    H[j] = temp
     
# Insert the element to the
# priority queue
insert(45)
insert(20)
insert(14)
insert(12)
insert(31)
insert(7)
insert(11)
insert(13)
insert(7)
   
i = 0
   
# Priority queue before extracting max
print("Priority Queue : ", end = "")
while (i <= size) :
 
    print(H[i], end = " ")
    i += 1
   
print()
   
# Node with maximum priority
print("Node with maximum priority :" ,  extractMax())
   
# Priority queue after extracting max
print("Priority queue after extracting maximum : ", end = "")
j = 0
while (j <= size) :
 
    print(H[j], end = " ")
    j += 1
   
print()
   
# Change the priority of element
# present at index 2 to 49
changePriority(2, 49)
print("Priority queue after priority change : ", end = "")
k = 0
while (k <= size) :
 
    print(H[k], end = " ")
    k += 1
   
print()
   
# Remove element at index 3
Remove(3)
print("Priority queue after removing the element : ", end = "")
l = 0
while (l <= size) :
 
    print(H[l], end = " ")
    l += 1
     
    # This code is contributed by divyeshrabadiya07.


C#
// C# code to implement priority-queue
// using array implementation of
// binary heap
using System;
 
class GFG{
 
static int []H = new int[50];
static int size = -1;
 
// Function to return the index of the
// parent node of a given node
static int parent(int i)
{
    return (i - 1) / 2;
}
 
// Function to return the index of the
// left child of the given node
static int leftChild(int i)
{
    return ((2 * i) + 1);
}
 
// Function to return the index of the
// right child of the given node
static int rightChild(int i)
{
    return ((2 * i) + 2);
}
 
// Function to shift up the
// node in order to maintain
// the heap property
static void shiftUp(int i)
{
    while (i > 0 &&
           H[parent(i)] < H[i])
    {
         
        // Swap parent and current node
        swap(parent(i), i);
     
        // Update i to parent of i
        i = parent(i);
    }
}
 
// Function to shift down the node in
// order to maintain the heap property
static void shiftDown(int i)
{
    int maxIndex = i;
     
    // Left Child
    int l = leftChild(i);
     
    if (l <= size &&
        H[l] > H[maxIndex])
    {
        maxIndex = l;
    }
     
    // Right Child
    int r = rightChild(i);
     
    if (r <= size &&
        H[r] > H[maxIndex])
    {
        maxIndex = r;
    }
     
    // If i not same as maxIndex
    if (i != maxIndex)
    {
        swap(i, maxIndex);
        shiftDown(maxIndex);
    }
}
 
// Function to insert a
// new element in
// the Binary Heap
static void insert(int p)
{
    size = size + 1;
    H[size] = p;
     
    // Shift Up to maintain
    // heap property
    shiftUp(size);
}
 
// Function to extract
// the element with
// maximum priority
static int extractMax()
{
    int result = H[0];
     
    // Replace the value
    // at the root with
    // the last leaf
    H[0] = H[size];
    size = size - 1;
     
    // Shift down the replaced
    // element to maintain the
    // heap property
    shiftDown(0);
    return result;
}
 
// Function to change the priority
// of an element
static void changePriority(int i,
                           int p)
{
    int oldp = H[i];
    H[i] = p;
     
    if (p > oldp)
    {
        shiftUp(i);
    }
    else
    {
        shiftDown(i);
    }
}
 
// Function to get value of
// the current maximum element
static int getMax()
{
    return H[0];
}
 
// Function to remove the element
// located at given index
static void Remove(int i)
{
    H[i] = getMax() + 1;
     
    // Shift the node to the root
    // of the heap
    shiftUp(i);
     
    // Extract the node
    extractMax();
}
 
static void swap(int i, int j)
{
    int temp = H[i];
    H[i] = H[j];
    H[j] = temp;
}
 
// Driver Code
public static void Main(String[] args)
{
 
/*              45
            /     \
           31      14
          / \     / \
        13  20   7   11
       / \
      12  7
    Create a priority queue shown in
    example in a binary max heap form.
    Queue will be represented in the
    form of array as:
    45 31 14 13 20 7 11 12 7 */
 
    // Insert the element to the
    // priority queue
    insert(45);
    insert(20);
    insert(14);
    insert(12);
    insert(31);
    insert(7);
    insert(11);
    insert(13);
    insert(7);
     
    int i = 0;
     
    // Priority queue before extracting max
    Console.Write("Priority Queue : ");
    while (i <= size)
    {
        Console.Write(H[i] + " ");
        i++;
    }
     
    Console.Write("\n");
     
    // Node with maximum priority
    Console.Write("Node with maximum priority : " +
                   extractMax() + "\n");
     
    // Priority queue after extracting max
    Console.Write("Priority queue after " +
                  "extracting maximum : ");
    int j = 0;
    while (j <= size)
    {
        Console.Write(H[j] + " ");
        j++;
    }
     
    Console.Write("\n");
     
    // Change the priority of element
    // present at index 2 to 49
    changePriority(2, 49);
    Console.Write("Priority queue after " +
                  "priority change : ");
    int k = 0;
    while (k <= size)
    {
        Console.Write(H[k] + " ");
        k++;
    }
     
    Console.Write("\n");
     
    // Remove element at index 3
    Remove(3);
    Console.Write("Priority queue after " +
                  "removing the element : ");
    int l = 0;
    while (l <= size)
    {
        Console.Write(H[l] + " ");
        l++;
    }
}
}
 
// This code is contributed by Amit Katiyar


输出:
Priority Queue : 45 31 14 13 20 7 11 12 7 
Node with maximum priority : 45 
Priority queue after extracting maximum : 31 20 14 13 7 7 11 12 
Priority queue after priority change : 49 20 31 13 7 7 11 12 
Priority queue after removing the element : 49 20 31 12 7 7 11

时间复杂度:除GetMax()的时间复杂度为O(1)之外,所有操作的时间复杂度均为O(log N )。
辅助空间: O(N)