Priority Queue 是队列的扩展,具有以下属性:
- 每个项目都有与之关联的优先级。
- 高优先级元素在低优先级元素之前出列。
- 如果两个元素具有相同的优先级,则根据它们在队列中的顺序提供服务。
二叉堆是具有以下属性的二叉树:
- 它是一棵完整的树。二叉堆的这个特性使得它们适合存储在数组中。
- 二叉堆是Min Heap或Max Heap 。
- 在最小二叉堆中,根的键必须是二叉堆中所有键中的最小键。对于二叉树中的所有节点,相同的属性必须递归为真。
- 类似地,在最大二叉堆中,根的键必须是二叉堆中所有键中的最大值。对于二叉树中的所有节点,相同的属性必须递归为真。
二叉堆上的操作
- insert(p):插入一个优先级为p的新元素。
- extractMax():提取具有最大优先级的元素。
- remove(i):删除迭代器 i 指向的元素。
- getMax():返回具有最大优先级的元素。
- changePriority(i, p):将i指向的元素的优先级更改为p 。
二元最大堆示例
- 假设下面是给定的二叉堆,它遵循二叉最大堆的所有属性。
- 现在需要在上面的堆中插入一个值为32的节点:要插入一个元素,将新元素附加到任何叶子上。例如,可以将优先级为32的节点添加到节点11的叶节点。但这违反了堆属性。为了保持堆属性,将新节点32 上移。
- Shift Up 操作 get node with 32 at the right position:将错误放置的节点与其父节点交换,直到满足堆属性。例如:由于节点11小于节点32,所以交换节点11和节点32 。然后,交换节点14和节点32 。最后,交换节点31和节点32 。
- ExtractMax:最大值存储在树的根部。但是树的根不能直接删除。首先,它被任何一片叶子替换,然后被移除。例如:要删除节点 45 ,首先将其替换为节点11 。但这违反了堆属性,因此将替换的节点向下移动。为此,请使用下移操作。
- ShiftDown 操作:将错误放置的节点与更大的子节点交换,直到满足堆属性。例如:节点11与节点32交换,然后与节点31交换,最后与节点14交换。
- ChangePriority:根据其优先级是降低还是提高,让改变的元素向上或向下移动。例如:将节点11的优先级更改为 35 ,由于此更改,节点必须向上移动节点以维护堆属性。
- 移除:要移除元素,将其优先级更改为大于当前最大值的值,然后将其向上移动,然后使用提取最大值提取它。使用 getMax 查找当前最大值。
- GetMax:最大值存储在树的根部。要获取最大值,只需返回树根处的值。
二叉堆的数组表示
由于堆以完全二叉树的形式维护,因此可以以数组的形式表示堆。为了保持树的完整和浅,在插入新元素时,将其插入到最后一层最左边的空白位置,即数组的末尾。类似地,在提取最大值时,将根替换为最后一层的最后一片叶子,即数组的最后一个元素。下面是相同的插图:
下面是使用二叉堆实现优先队列的程序:
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
时间复杂度:所有操作的时间复杂度为O(log N),除了 GetMax() 的时间复杂度为 O(1)。
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。