优先队列和二叉堆

优先队列是一种常用的ADT,其中的元素有序排列,入队的元素会插入到正确的位置,队首元素始终为最小(大)值,队首出队后优先队列仍然保持原来的性质。

这里我们规定优先队列以升序排列。

优先队列提供的接口包括:

  • insert 插入元素
  • top 得到队首元素
  • pop 删除队首元素

二叉堆是优先队列一种常用的实现,二叉堆是一种完全二叉树,完全二叉树除最低一层外其它层均被填满,最低一层的节点全部集中在左侧。完全二叉树的性质决定它可以很容易地由二叉数组来实现。

二叉堆满足堆序性,即任意一个节点X的父节点不大于X(最小堆)。由堆序性可知,二叉堆的根节点一定为最小值或最大值,根节点为最小值的堆称为最小堆,根节点为最大值的堆称为最大堆。

最小堆类的声明:

template
class MinHeap {
protected:
const static size_t capcity = 10000;
size_t size;
val_t vec[capcity];
public:
MinHeap();
void insert(val_t val);
bool empty();
void rmMin();
val_t getMin() {
return vec[1];
};
~MinHeap() = default;
};

插入元素

插入元素采用上滤的方法:

(1)在数组超出末端(size位置)创建一个空穴

(2)比较新元素与空穴父节点的大小,若新元素较大则将原父节点填入空穴,原父节点的位置变为空穴

(3)直至新元素不大于空穴父节点时停止空穴上溯

template
void MinHeap<val_t>::insert(val_t val) {
size_t i;
for (i = ++size; vec[i/2] > val; i /= 2) {
vec[i] = vec[i / 2];
}
vec[i] = val;
}

在实现过程中,我们只是用i标记了空穴的位置,并没有交换空穴与父节点的位置。

删除根元素

删除元素采用恰好相反的下滤策略:

(1) 移除根节点后在根节点处产生了一个空穴

(2) 比较空穴的左右子节点,较大的一个与空穴交换位置,直至空穴到达最下层

(3) 将原来最后一个元素填入空穴的位置

template
void MinHeap<val_t>::rmMin() {
size_t i, next;
val_t min, last;
if (empty()) {
return;
}
min = vec[1];
last = vec[size--];
for (i = 1; i * 2 <= size; i = next) {
//find smaller next
next = i * 2;
if (next != size && vec[next + 1] < vec[next]) {
next++;
}
//
if (last > vec[next]) {
vec[i] = vec[next];
}
else {
break;
}
}
vec[i] = last;
}

一言不发就丢代码:

include

//#include

using namespace std;

template
class MinHeap {
protected:
const static size_t capcity = 10000;
size_t size;
val_t vec[capcity];
public:
MinHeap();
void insert(val_t val);
bool empty();
void rmMin();
val_t getMin() {
return vec[1];
};
~MinHeap() = default;
};

template
MinHeap<val_t>::MinHeap() {
size = 0;
}

template
bool MinHeap<val_t>::empty() {
if (size) {
return false;
}
else {
return true;
}
}

template
void MinHeap<val_t>::insert(val_t val) {
size_t i;
for (i = ++size; vec[i/2] > val; i /= 2) { //covert > to <, to get a max heap
vec[i] = vec[i / 2];
}
vec[i] = val;
}

template
void MinHeap<val_t>::rmMin() {
size_t i, next;
val_t min, last;
if (empty()) {
return;
}
min = vec[1];
last = vec[size--];
for (i = 1; i * 2 <= size; i = next) {
//find smaller next
next = i * 2;
if (next != size && vec[next + 1] < vec[next]) {
next++;
}
//
if (last > vec[next]) {
vec[i] = vec[next];
}
else {
break;
}
}
vec[i] = last;
}

posted @ 2016-05-07 21:11  -Finley-  阅读(314)  评论(0)    收藏  举报