您的位置:首页 > 编程语言 > C语言/C++

二项堆(二)之 C++的实现

2014-04-15 09:28 2091 查看

 

概要

上一章介绍了二项堆的基本概念,并通过C语言实现了二项堆。本章是二项堆的C++实现。

目录
1. 二项树的介绍
2. 二项堆的介绍
3. 二项堆的基本操作
4. 二项堆的C++实现(完整源码)
5. 二项堆的C++测试程序

转载请注明出处:https://www.geek-share.com/detail/2608525284.html

更多内容:数据结构与算法系列 目录

(01) 二项堆(一)之 图文解析 和 C语言的实现
(02) 二项堆(二)之 C++的实现
(03) 二项堆(二)之 Java的实现

 

二项树的介绍

二项树的定义

二项堆是二项树的集合。在了解二项堆之前,先对二项树进行介绍。

二项树是一种递归定义的有序树。它的递归定义如下:
(01) 二项树B0只有一个结点;
(02) 二项树Bk由两棵二项树B(k-1)组成的,其中一棵树是另一棵树根的最左孩子。
如下图所示:

/*
* 将h1, h2中的根表合并成一个按度数递增的链表,返回合并后的根节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::merge(BinomialNode<T>* h1, BinomialNode<T>* h2)
{
BinomialNode<T>* root = NULL; //heap为指向新堆根结点
BinomialNode<T>** pos = &root;

while (h1 && h2)
{
if (h1->degree < h2->degree)
{
*pos = h1;
h1 = h1->next;
}
else
{
*pos = h2;
h2 = h2->next;
}
pos = &(*pos)->next;
}
if (h1)
*pos = h1;
else
*pos = h2;

return root;
}
View Code link()代码(C++)

/*
* 合并两个二项堆:将child合并到root中
*/
template <class T>
void BinomialHeap<T>::link(BinomialNode<T>* child, BinomialNode<T>* root)
{
child->parent = root;
child->next   = root->child;
root->child = child;
root->degree++;
}
View Code

合并操作代码(C++)

/*
* 合并二项堆:将h1, h2合并成一个堆,并返回合并后的堆
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::combine(BinomialNode<T>* h1, BinomialNode<T>* h2)
{
BinomialNode<T> *root;
BinomialNode<T> *prev_x, *x, *next_x;

// 将h1, h2中的根表合并成一个按度数递增的链表root
root = merge(h1, h2);
if (root == NULL)
return NULL;

prev_x = NULL;
x      = root;
next_x = x->next;

while (next_x != NULL)
{
if (   (x->degree != next_x->degree)
|| ((next_x->next != NULL) && (next_x->degree == next_x->next->degree)))
{
// Case 1: x->degree != next_x->degree
// Case 2: x->degree == next_x->degree == next_x->next->degree
prev_x = x;
x = next_x;
}
else if (x->key <= next_x->key)
{
// Case 3: x->degree == next_x->degree != next_x->next->degree
//      && x->key    <= next_x->key
x->next = next_x->next;
link(next_x, x);
}
else
{
// Case 4: x->degree == next_x->degree != next_x->next->degree
//      && x->key    >  next_x->key
if (prev_x == NULL)
{
root = next_x;
}
else
{
prev_x->next = next_x;
}
link(x, next_x);
x = next_x;
}
next_x = x->next;
}

return root;
}

/*
* 将二项堆other合并到当前堆中
*/
template <class T>
void BinomialHeap<T>::combine(BinomialHeap<T> *other)
{
if (other!=NULL && other->mRoot!=NULL)
mRoot = combine(mRoot, other->mRoot);
}

合并函数combine(h1, h2)的作用是将h1和h2合并,并返回合并后的二项堆。在combine(h1, h2)中,涉及到了两个函数merge(h1, h2)和link(child, root)。
merge(h1, h2)就是我们前面所说的"两个二项堆的根链表合并成一个链表,合并后的新链表按照'节点的度数'单调递增排序"。
link(child, root)则是为了合并操作的辅助函数,它的作用是将"二项堆child的根节点"设为"二项堆root的左孩子",从而将child整合到root中去。

        在combine(h1, h2)中对h1和h2进行合并时;首先通过 merge(h1, h2) 将h1和h2的根链表合并成一个"按节点的度数单调递增"的链表;然后进入while循环,对合并得到的新链表进行遍历,将新链表中"根节点度数相同的二项树"连接起来,直到所有根节点度数都不相同为止。在将新联表中"根节点度数相同的二项树"连接起来时,可以将被连接的情况概括为4种。

x是根链表的当前节点,next_x是x的下一个(兄弟)节点。
Case 1: x->degree != next_x->degree
             即,"当前节点的度数"与"下一个节点的度数"相等时。此时,不需要执行任何操作,继续查看后面的节点。
Case 2: x->degree == next_x->degree == next_x->next->degree
             即,"当前节点的度数"、"下一个节点的度数"和"下下一个节点的度数"都相等时。此时,暂时不执行任何操作,还是继续查看后面的节点。实际上,这里是将"下一个节点"和"下下一个节点"等到后面再进行整合连接。
Case 3: x->degree == next_x->degree != next_x->next->degree
        && x->key <= next_x->key
             即,"当前节点的度数"与"下一个节点的度数"相等,并且"当前节点的键值"<="下一个节点的度数"。此时,将"下一个节点(对应的二项树)"作为"当前节点(对应的二项树)的左孩子"。
Case 4: x->degree == next_x->degree != next_x->next->degree
        && x->key > next_x->key
             即,"当前节点的度数"与"下一个节点的度数"相等,并且"当前节点的键值">"下一个节点的度数"。此时,将"当前节点(对应的二项树)"作为"下一个节点(对应的二项树)的左孩子"。


下面通过示意图来对合并操作进行说明。

/*
* 反转二项堆root,并返回反转后的根节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::reverse(BinomialNode<T>* root)
{
BinomialNode<T>* next;
BinomialNode<T>* tail = NULL;

if (!root)
return root;

root->parent = NULL;
while (root->next)
{
next          = root->next;
root->next = tail;
tail          = root;
root          = next;
root->parent  = NULL;
}
root->next = tail;

return root;
}
View Code 删除操作代码(C++)

/*
* 删除节点:删除键值为key的节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::remove(BinomialNode<T>* root, T key)
{
BinomialNode<T> *node;
BinomialNode<T> *parent, *prev, *pos;

if (root==NULL)
return root;

// 查找键值为key的节点
if ((node = search(root, key)) == NULL)
return root;

// 将被删除的节点的数据数据上移到它所在的二项树的根节点
parent = node->parent;
while (parent != NULL)
{
// 交换数据
swap(node->key, parent->key);
// 下一个父节点
node   = parent;
parent = node->parent;
}

// 找到node的前一个根节点(prev)
prev = NULL;
pos  = root;
while (pos != node)
{
prev = pos;
pos  = pos->next;
}
// 移除node节点
if (prev)
prev->next = node->next;
else
root = node->next;

root = combine(root, reverse(node->child));

delete node;

return root;
}

template <class T>
void BinomialHeap<T>::remove(T key)
{
mRoot = remove(mRoot, key);
}

remove(key)的作用是删除二项堆中键值为key的节点,并返回删除节点后的二项堆。
reverse(root)的作用是反转二项堆root,并返回反转之后的根节点。


下面通过示意图来对删除操作进行说明(删除二项堆中的节点20)。

/*
* 更新二项堆的节点node的键值为key
*/
template <class T>
void BinomialHeap<T>::updateKey(BinomialNode<T>* node, T key)
{
if (node == NULL)
return ;

if(key < node->key)
decreaseKey(node, key);
else if(key > node->key)
increaseKey(node, key);
else
cout <<"No need to update!!!" <<endl;
}

/*
* 将二项堆中键值oldkey更新为newkey
*/
template <class T>
void BinomialHeap<T>::update(T oldkey, T newkey)
{
BinomialNode<T> *node;

node = search(mRoot, oldkey);
if (node != NULL)
updateKey(node, newkey);
}
View Code  

5.1 减少节点的值

减少节点值的操作很简单:该节点一定位于一棵二项树中,减小"二项树"中某个节点的值后要保证"该二项树仍然是一个最小堆";因此,就需要我们不断的将该节点上调。

减少操作代码(C++)

/*
* 减少关键字的值:将二项堆中的节点node的键值减小为key。
*/
template <class T>
void BinomialHeap<T>::decreaseKey(BinomialNode<T>* node, T key)
{
if(key>=node->key || contains(key))
{
cout << "decrease failed: the new key(" << key <<") is existed already, "
<< "or is no smaller than current key(" << node->key <<")" << endl;
return ;
}
node->key = key;

BinomialNode<T> *child, *parent;
child = node;
parent = node->parent;
while(parent != NULL && child->key < parent->key)
{
swap(parent->key, child->key);
child = parent;
parent = child->parent;
}
}

 

下面是减少操作的示意图(20->2)

/**
* C++: 二项堆
*
* @author skywang
* @date 2014/04/02
*/

#ifndef _BINOMIAL_TREE_HPP_
#define _BINOMIAL_TREE_HPP_

#include <iomanip>
#include <iostream>
using namespace std;

template <class T>
class BinomialNode {
public:
T key;                      // 关键字(键值)
int degree;                 // 度数
BinomialNode<T> *child;     // 左孩子
BinomialNode<T> *parent;    // 父节点
BinomialNode<T> *next;      // 兄弟节点

BinomialNode(T value):key(value), degree(0),
child(NULL),parent(NULL),next(NULL) {}
};

template <class T>
class BinomialHeap {
private:
BinomialNode<T> *mRoot;    // 根结点

public:
BinomialHeap();
~BinomialHeap();

// 新建key对应的节点,并将其插入到二项堆中
void insert(T key);
// 将二项堆中键值oldkey更新为newkey
void update(T oldkey, T newkey);
// 删除键值为key的节点
void remove(T key);
// 移除二项堆中的最小节点
void extractMinimum();

// 将other的二项堆合并到当前二项堆中
void combine(BinomialHeap<T>* other);

// 获取二项堆中的最小节点的键值
T minimum();
// 二项堆中是否包含键值key
bool contains(T key);
// 打印二项堆
void print();
private:

// 合并两个二项堆:将child合并到root中
void link(BinomialNode<T>* child, BinomialNode<T>* root);
// 将h1, h2中的根表合并成一个按度数递增的链表,返回合并后的根节点
BinomialNode<T>* merge(BinomialNode<T>* h1, BinomialNode<T>* h2);
// 合并二项堆:将h1, h2合并成一个堆,并返回合并后的堆
BinomialNode<T>* combine(BinomialNode<T>* h1, BinomialNode<T>* h2);
// 反转二项堆root,并返回反转后的根节点
BinomialNode<T>* reverse(BinomialNode<T>* root);
// 移除二项堆root中的最小节点,并返回删除节点后的二项树
BinomialNode<T>* extractMinimum(BinomialNode<T>* root);
// 删除节点:删除键值为key的节点,并返回删除节点后的二项树
BinomialNode<T>* remove(BinomialNode<T> *root, T key);
// 在二项树root中查找键值为key的节点
BinomialNode<T>* search(BinomialNode<T>* root, T key);

// 增加关键字的值:将二项堆中的节点node的键值增加为key。
void increaseKey(BinomialNode<T>* node, T key);
// 减少关键字的值:将二项堆中的节点node的键值减小为key
void decreaseKey(BinomialNode<T>* node, T key);
// 更新关键字的值:更新二项堆的节点node的键值为key
void updateKey(BinomialNode<T>* node, T key);

// 获取二项堆中的最小根节点
void minimum(BinomialNode<T>* root, BinomialNode<T> *&prev_y, BinomialNode<T> *&y);
// 打印二项堆
void print(BinomialNode<T>* node, BinomialNode<T>* prev, int direction);
};

/*
* 构造函数
*/
template <class T>
BinomialHeap<T>::BinomialHeap():mRoot(NULL)
{
}

/*
* 析构函数
*/
template <class T>
BinomialHeap<T>::~BinomialHeap()
{
}

/*
* 获取二项堆中的最小根节点
*
* 参数说明:
*     root    -- 二项堆
*     prev_y  -- [输出参数]最小根节点y的前一个根节点
*     y       -- [输出参数]最小根节点
*/
template <class T>
void BinomialHeap<T>::minimum(BinomialNode<T>* root,
BinomialNode<T> *&prev_y, BinomialNode<T> *&y)
{
BinomialNode<T> *x, *prev_x;    // x是用来遍历的当前节点

if (root==NULL)
return ;

prev_x  = root;
x       = root->next;
prev_y = NULL;
y      = root;
// 找到最小节点
while (x != NULL) {
if (x->key < y->key) {
y = x;
prev_y = prev_x;
}
prev_x = x;
x = x->next;
}
}

/*
* 获取二项堆中的最小节点的键值
*/
template <class T>
T BinomialHeap<T>::minimum()
{
BinomialNode<T> *prev_y, *y;

minimum(mRoot, prev_y, y);

return y->key;
}

/*
* 合并两个二项堆:将child合并到root中
*/
template <class T>
void BinomialHeap<T>::link(BinomialNode<T>* child, BinomialNode<T>* root)
{
child->parent = root;
child->next   = root->child;
root->child = child;
root->degree++;
}

/*
* 将h1, h2中的根表合并成一个按度数递增的链表,返回合并后的根节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::merge(BinomialNode<T>* h1, BinomialNode<T>* h2)
{
BinomialNode<T>* root = NULL; //heap为指向新堆根结点
BinomialNode<T>** pos = &root;

while (h1 && h2)
{
if (h1->degree < h2->degree)
{
*pos = h1;
h1 = h1->next;
}
else
{
*pos = h2;
h2 = h2->next;
}
pos = &(*pos)->next;
}
if (h1)
*pos = h1;
else
*pos = h2;

return root;
}

/*
* 合并二项堆:将h1, h2合并成一个堆,并返回合并后的堆
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::combine(BinomialNode<T>* h1, BinomialNode<T>* h2)
{
BinomialNode<T> *root;
BinomialNode<T> *prev_x, *x, *next_x;

// 将h1, h2中的根表合并成一个按度数递增的链表root
root = merge(h1, h2);
if (root == NULL)
return NULL;

prev_x = NULL;
x      = root;
next_x = x->next;

while (next_x != NULL)
{
if (   (x->degree != next_x->degree)
|| ((next_x->next != NULL) && (next_x->degree == next_x->next->degree)))
{
// Case 1: x->degree != next_x->degree
// Case 2: x->degree == next_x->degree == next_x->next->degree
prev_x = x;
x = next_x;
}
else if (x->key <= next_x->key)
{
// Case 3: x->degree == next_x->degree != next_x->next->degree
//      && x->key    <= next_x->key
x->next = next_x->next;
link(next_x, x);
}
else
{
// Case 4: x->degree == next_x->degree != next_x->next->degree
//      && x->key    >  next_x->key
if (prev_x == NULL)
{
root = next_x;
}
else
{
prev_x->next = next_x;
}
link(x, next_x);
x = next_x;
}
next_x = x->next;
}

return root;
}

/*
* 将二项堆other合并到当前堆中
*/
template <class T>
void BinomialHeap<T>::combine(BinomialHeap<T> *other)
{
if (other!=NULL && other->mRoot!=NULL)
mRoot = combine(mRoot, other->mRoot);
}

/*
* 新建key对应的节点,并将其插入到二项堆中。
*/
template <class T>
void BinomialHeap<T>::insert(T key)
{
BinomialNode<T>* node;

// 禁止插入相同的键值
if (contains(key))
{
cout << "Insert Error: the key (" << key << ") is existed already!" << endl;
return ;
}

node = new BinomialNode<T>(key);
if (node==NULL)
return ;

mRoot = combine(mRoot, node);
}

/*
* 反转二项堆root,并返回反转后的根节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::reverse(BinomialNode<T>* root)
{
BinomialNode<T>* next;
BinomialNode<T>* tail = NULL;

if (!root)
return root;

root->parent = NULL;
while (root->next)
{
next          = root->next;
root->next = tail;
tail          = root;
root          = next;
root->parent  = NULL;
}
root->next = tail;

return root;
}

/*
* 移除二项堆root中的最小节点,并返回删除节点后的二项树
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::extractMinimum(BinomialNode<T>* root)
{
BinomialNode<T> *y, *prev_y;    // y是最小节点

if (root==NULL)
return root;

// 找到"最小节点根y"和"它的前一个根节点prev_y"
minimum(root, prev_y, y);

if (prev_y == NULL)    // root的根节点就是最小根节点
root = root->next;
else                // root的根节点不是最小根节点
prev_y->next = y->next;

// 反转最小节点的左孩子,得到最小堆child;
// 这样,就使得最小节点所在二项树的孩子们都脱离出来成为一棵独立的二项树(不包括最小节点)
BinomialNode<T>* child = reverse(y->child);
// 将"删除最小节点的二项堆child"和"root"进行合并。
root = combine(root, child);

// 删除最小节点
delete y;

return root;
}

template <class T>
void BinomialHeap<T>::extractMinimum()
{
mRoot = extractMinimum(mRoot);
}

/*
* 减少关键字的值:将二项堆中的节点node的键值减小为key。
*/
template <class T>
void BinomialHeap<T>::decreaseKey(BinomialNode<T>* node, T key)
{
if(key>=node->key || contains(key))
{
cout << "decrease failed: the new key(" << key <<") is existed already, "
<< "or is no smaller than current key(" << node->key <<")" << endl;
return ;
}
node->key = key;

BinomialNode<T> *child, *parent;
child = node;
parent = node->parent;
while(parent != NULL && child->key < parent->key)
{
swap(parent->key, child->key);
child = parent;
parent = child->parent;
}
}

/*
* 增加关键字的值:将二项堆中的节点node的键值增加为key。
*/
template <class T>
void BinomialHeap<T>::increaseKey(BinomialNode<T>* node, T key)
{
if(key<=node->key || contains(key))
{
cout << "decrease failed: the new key(" << key <<") is existed already, "
<< "or is no greater than current key(" << node->key <<")" << endl;
return ;
}

node->key = key;

BinomialNode<T> *cur, *child, *least;
cur = node;
child = cur->child;
while (child != NULL)
{
if(cur->key > child->key)
{
// 如果"当前节点" < "它的左孩子",
// 则在"它的孩子中(左孩子 和 左孩子的兄弟)"中,找出最小的节点;
// 然后将"最小节点的值" 和 "当前节点的值"进行互换
least = child;
while(child->next != NULL)
{
if (least->key > child->next->key)
{
least = child->next;
}
child = child->next;
}
// 交换最小节点和当前节点的值
swap(least->key, cur->key);

// 交换数据之后,再对"原最小节点"进行调整,使它满足最小堆的性质:父节点 <= 子节点
cur = least;
child = cur->child;
}
else
{
child = child->next;
}
}
}

/*
* 更新二项堆的节点node的键值为key
*/
template <class T>
void BinomialHeap<T>::updateKey(BinomialNode<T>* node, T key)
{
if (node == NULL)
return ;

if(key < node->key)
decreaseKey(node, key);
else if(key > node->key)
increaseKey(node, key);
else
cout <<"No need to update!!!" <<endl;
}

/*
* 将二项堆中键值oldkey更新为newkey
*/
template <class T>
void BinomialHeap<T>::update(T oldkey, T newkey)
{
BinomialNode<T> *node;

node = search(mRoot, oldkey);
if (node != NULL)
updateKey(node, newkey);
}

/*
* 查找:在二项堆中查找键值为key的节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::search(BinomialNode<T>* root, T key)
{
BinomialNode<T> *child;
BinomialNode<T> *parent = root;

parent = root;
while (parent != NULL)
{
if (parent->key == key)
return parent;
else
{
if((child = search(parent->child, key)) != NULL)
return child;
parent = parent->next;
}
}

return NULL;
}

/*
* 二项堆中是否包含键值key
*/
template <class T>
bool BinomialHeap<T>::contains(T key)
{
return search(mRoot, key)!=NULL ? true : false;
}

/*
* 删除节点:删除键值为key的节点
*/
template <class T>
BinomialNode<T>* BinomialHeap<T>::remove(BinomialNode<T>* root, T key)
{
BinomialNode<T> *node;
BinomialNode<T> *parent, *prev, *pos;

if (root==NULL)
return root;

// 查找键值为key的节点
if ((node = search(root, key)) == NULL)
return root;

// 将被删除的节点的数据数据上移到它所在的二项树的根节点
parent = node->parent;
while (parent != NULL)
{
// 交换数据
swap(node->key, parent->key);
// 下一个父节点
node   = parent;
parent = node->parent;
}

// 找到node的前一个根节点(prev)
prev = NULL;
pos  = root;
while (pos != node)
{
prev = pos;
pos  = pos->next;
}
// 移除node节点
if (prev)
prev->next = node->next;
else
root = node->next;

root = combine(root, reverse(node->child));

delete node;

return root;
}

template <class T>
void BinomialHeap<T>::remove(T key)
{
mRoot = remove(mRoot, key);
}

/*
* 打印"二项堆"
*
* 参数说明:
*     node       -- 当前节点
*     prev       -- 当前节点的前一个节点(父节点or兄弟节点)
*     direction  --  1,表示当前节点是一个左孩子;
*                    2,表示当前节点是一个兄弟节点。
*/
template <class T>
void BinomialHeap<T>::print(BinomialNode<T>* node, BinomialNode<T>* prev, int direction)
{
while(node != NULL)
{
if(direction==1)    // node是根节点
cout << "\t" << setw(2) << node->key << "(" << node->degree << ") is "<< setw(2) << prev->key << "'s child" << endl;
else                // node是分支节点
cout << "\t" << setw(2) << node->key << "(" << node->degree << ") is "<< setw(2) << prev->key << "'s next" << endl;

if (node->child != NULL)
print(node->child, node, 1);

// 兄弟节点
prev = node;
node = node->next;
direction = 2;
}
}

template <class T>
void BinomialHeap<T>::print()
{
BinomialNode<T> *p;
if (mRoot == NULL)
return ;

cout << "== 二项堆( ";
p = mRoot;
while (p != NULL)
{
cout << "B" << p->degree << " ";
p = p->next;
}
cout << ")的详细信息:" << endl;

int i=0;
p = mRoot;
while (p != NULL)
{
i++;
cout << i << ". 二项树B" << p->degree << ":" << endl;
cout << "\t" << setw(2) << p->key << "(" << p->degree << ") is root" << endl;

print(p->child, p, 1);
p = p->next;
}
cout << endl;
}
#endif
View Code 二项堆的测试程序(Main.cpp)

/**
* C 语言: 二项堆
*
* @author skywang
* @date 2014/04/02
*/

#include <iostream>
#include "BinomialHeap.h"
using namespace std;

#define DEBUG 0

// 共7个 = 1+2+4
int a[] = {12,  7, 25, 15, 28,
33, 41};
// 共13个 = 1+4+8
int b[] = {18, 35, 20, 42,  9,
31, 23,  6, 48, 11,
24, 52, 13 };

// 验证"二项堆的插入操作"
void testInsert()
{
int i;
int alen=sizeof(a)/sizeof(a[0]);
BinomialHeap<int>* ha=new BinomialHeap<int>();

cout << "== 二项堆(ha)中依次添加: ";
for(i=0; i<alen; i++)
{
cout << a[i] <<" ";
ha->insert(a[i]);
}
cout << endl;
cout << "== 二项堆(ha)的详细信息: " << endl;
ha->print();
}

// 验证"二项堆的合并操作"
void testUnion()
{
int i;
int alen=sizeof(a)/sizeof(a[0]);
int blen=sizeof(b)/sizeof(b[0]);
BinomialHeap<int>* ha=new BinomialHeap<int>();
BinomialHeap<int>* hb=new BinomialHeap<int>();

cout << "== 二项堆(ha)中依次添加: ";
for(i=0; i<alen; i++)
{
cout << a[i] <<" ";
ha->insert(a[i]);
}
cout << endl;
cout << "== 二项堆(ha)的详细信息: " << endl;
ha->print();

cout << "== 二项堆(hb)中依次添加: ";
for(i=0; i<blen; i++)
{
cout << b[i] <<" ";
hb->insert(b[i]);
}
cout << endl;
cout << "== 二项堆(hb)的详细信息: " << endl;
hb->print();

// 将"二项堆hb"合并到"二项堆ha"中。
ha->combine(hb);
cout << "== 合并ha和hb后的详细信息: " << endl;
ha->print();
}

// 验证"二项堆的删除操作"
void testDelete()
{
int i;
int blen=sizeof(b)/sizeof(b[0]);
BinomialHeap<int>* hb=new BinomialHeap<int>();

cout << "== 二项堆(hb)中依次添加: ";
for(i=0; i<blen; i++)
{
cout << b[i] <<" ";
hb->insert(b[i]);
}
cout << endl;
cout << "== 二项堆(hb)的详细信息: " << endl;
hb->print();

// 将"二项堆hb"合并到"二项堆ha"中。
hb->remove(20);
cout << "== 删除节点20后的详细信息: " << endl;
hb->print();
}

// 验证"二项堆的更新(减少)操作"
void testDecrease()
{
int i;
int blen=sizeof(b)/sizeof(b[0]);
BinomialHeap<int>* hb=new BinomialHeap<int>();

cout << "== 二项堆(hb)中依次添加: ";
for(i=0; i<blen; i++)
{
cout << b[i] <<" ";
hb->insert(b[i]);
}
cout << endl;
cout << "== 二项堆(hb)的详细信息: " << endl;
hb->print();

// 将节点20更新为2
hb->update(20, 2);
cout << "== 更新节点20->2后的详细信息: " << endl;
hb->print();
}

// 验证"二项堆的更新(增加)操作"
void testIncrease()
{
int i;
int blen=sizeof(b)/sizeof(b[0]);
BinomialHeap<int>* hb=new BinomialHeap<int>();

cout << "== 二项堆(hb)中依次添加: ";
for(i=0; i<blen; i++)
{
cout << b[i] <<" ";
hb->insert(b[i]);
}
cout << endl;
cout << "== 二项堆(hb)的详细信息: " << endl;
hb->print();

// 将节点6更新为60
hb->update(6, 60);
cout << "== 更新节点6->60后的详细信息: " << endl;
hb->print();
}

int main()
{
// 1. 验证"二项堆的插入操作"
testInsert();
// 2. 验证"二项堆的合并操作"
//testUnion();
// 3. 验证"二项堆的删除操作"
//testDelete();
// 4. 验证"二项堆的更新(减少)操作"
//testDecrease();
// 5. 验证"二项堆的更新(增加)操作"
//testIncrease();

return 0;
}
View Code

 

二项堆的C++测试程序

二项堆的测试程序包括了五部分,分别是"插入"、"删除"、"增加"、"减少"、"合并"这5种功能的测试代码。默认是运行的"插入"功能代码,你可以根据自己的需要来对相应的功能进行验证!

下面是插入功能运行结果:

== 二项堆(ha)中依次添加: 12 7 25 15 28 33 41
== 二项堆(ha)的详细信息:
== 二项堆( B0 B1 B2 )的详细信息:
1. 二项树B0:
41(0) is root
2. 二项树B1:
28(1) is root
33(0) is 28's child
3. 二项树B2:
7(2) is root
15(1) is  7's child
25(0) is 15's child
12(0) is 15's next

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: