《算法导论》第3版6.5讲解了优先队列
优先队列(priority queue)是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字(key)。
一个最大优先队列支持以下操作:
1) insert(S, x): 把元素x插入集合S中,这一操作等价于S=S∪{x}
2) maximum(S): 返回S中具有最大键字的元素
3) extract_max(S): 去掉并返回S中具有最大键字的元素
4) increase_key(S, x, k): 将元素x的关键字增加到k,这里假设k的值不小于x的原关键字值
1)max_heap_insert:
void max_heap_insert(int A[], int key)
{
++heap_size;
A[heap_size - 1] = INT_MIN;
heap_increase_key(A, heap_size - 1, key);
}
2)heap_maximum:
int heap_maximum(int A[])
{
return A[0];
}
3)heap_extract_max:
int heap_extract_max(int A[])
{
if (heap_size < 1)
{
cout << "heap underflow" << endl;
return -1;
}
int max = A[0];
A[0] = A[heap_size - 1];
--heap_size;
max_heapify(A, 0);
return max;
}
4)heap_increase_key:
void heap_increase_key(int A[], int i, int key)
{
if (key < A[i])
{
cout << "new key is smaller than current key" << endl;
return;
}
A[i] = key;
while (i > 0 && A[parent(i)] < A[i])
{
swap(A[i], A[parent(i)]);
i = parent(i);
}
}
在《算法导论》第3版习题6.5-6提到:
在heap_increase_key的第5行的交换操作中,一般需要通过三次赋值来完成。想一想如何利用insertion_sort内循环部分的思想,只用一次赋值就完成这一交换操作?
思路:先向下移动小于key的祖先,直到没有小于key的祖先后放在空出的位置上
void heap_increase_key_oneassign(int A[], int i, int key)
{
if (key < A[i])
{
cout << "new key is smaller than current key" << endl;
return;
}
while (i > 0 && A[parent(i)] < key)
{
A[i] = A[parent(i)];
i = parent(i);
}
A[i] = key;
}
在《算法导论》第3版习题6.5-8提到:
heap_delete(A, i)操作能够将结点i从堆A中删除。对于一个包含n个元素的堆,请设计一个能够在O(logn)时间内完成的heap_delete操作。
void heap_delete(int A[], int i)
{
swap(A[i], A[heap_size - 1]);
--heap_size;
max_heapify(A, i);
}
void heap_delete_thevalue(int A[], int target)
{
int tag = -1;
for (int i = 0; i < heap_size; ++i)
{
if (A[i] == target)
{
tag = i;
break;
}
}
if (tag != -1)
heap_delete(A, tag);
}