heap.h
#ifndef _LEFTISTHEAP_H
#define _LEFTISTHEAP_H
using namespace std;
//虚基类
class baseHeap
{
public:
virtual void insert(int x) = 0;
};
//普通最小堆
class heap:public baseHeap
{
public:
int size;
int *a; //存储数据
heap(int n=10000); //构造函数
void merge(const heap &h); //与现有堆合并
void insert(int x); //插入
};
//左式堆
class leftistHeap:public baseHeap
{
struct leftistHeapNode { //结点
int element; //元素
leftistHeapNode *left; //左孩子
leftistHeapNode *right; //右孩子
int npl; //零路径长
leftistHeapNode(int x); //构造函数
};
public:
leftistHeapNode *root; //根节点
leftistHeap(leftistHeapNode *root = nullptr); //构造函数
static leftistHeapNode* Merge(leftistHeapNode* h1, leftistHeapNode* h2);//合并(实现函数)
void merge(const leftistHeap &h);//与现有堆合并(接口函数)
void insert(int x); //插入
};
//斜堆
class skewHeap:public baseHeap
{
struct skewHeapNode { //结点
int element; //元素
skewHeapNode *left; //左孩子
skewHeapNode *right; //右孩子
skewHeapNode(int x); //构造函数
};
public:
skewHeapNode *root; //根节点
skewHeap(skewHeapNode* root = nullptr); //构造函数
static skewHeapNode* Merge(skewHeapNode* h1, skewHeapNode* h2); //合并(实现函数)
void merge(const skewHeap &h);//与现有堆合并(接口函数)
void insert(int x); //插入
};
//全局合并函数
const skewHeap &merge(const skewHeap &h1, const skewHeap &h2);
const leftistHeap &merge(const leftistHeap &h1, const leftistHeap &h2);
const heap &merge(const heap &h1, const heap &h2);
void print(heap h);//打印堆(用于测试)
#endif
#ifndef _TEMPLATE_H
#define _TEMPLATE_H
#include"heap.h"
#include
#include
// 打印堆(左式堆,斜堆) 用于测试
// 层序遍历,按层输出
template
void print(T root)
{
if (!root)return;
int cur = 1;
int curnum = 1;
int nextnum = 0;
queueq; //队列
q.push(root);
while (!q.empty()) { //非空时
curnum--;
T tmp = q.front(); //当前队头元素出队列
cout << tmp->element << " ";
q.pop();
if (tmp->left) {
q.push(tmp->left); //左孩子入队列
nextnum++;
}
if (tmp->right) {
q.push(tmp->right); //右孩子入队列
nextnum++;
}
if (curnum == 0) { //控制按层输出
cout << endl;
cur++;
curnum = nextnum;
nextnum = 0;
}
}
cout << endl;
}
//交换孩子
template
void swapChild(T &h)
{
T tmp;
tmp = h->right;
h->right = h->left;
h->left = tmp;
}
#endif
#include"heap.h"
#include
#include
#include
#include
using namespace std;
heap::heap(int n) :size(0) {
a = (int*)malloc(sizeof(int)*(n+1));
a[0] = INT_MIN;
if (!a)printf("error\n");
}
//初始化大小为0,哨兵为最小值
void heap::merge(const heap &h)
{
int i;
//直接将外部堆插入
for (i = 1; i != size; i++) {
insert(h.a[i]);
}
}
const heap& merge(const heap &h1, const heap &h2)
{
int i;
heap *tmp = new heap(h1.size+h2.size);//新建一个堆
for (i = 1; i <= h1.size; i++) { //插入第一个堆
tmp->insert(h1.a[i]);
}
for (i = 1; i <= h2.size; i++) { //插入第二个堆
tmp->insert(h2.a[i]);
}
return *tmp; //返回新建堆
}
void heap::insert(int x)
{
int p = ++size; //大小加1
a[p] = x; //插入
int tmp = a[p];
for (; a[p / 2]>tmp; p /= 2) { //调整位置
a[p] = a[p / 2];
}
a[p] = tmp;
}
void print(heap h)
{
int i;
for (i = 1; i < h.size; i++) { //遍历输出
cout << h.a[i] << " ";
}
cout << endl;
}
#include"heap.h"
#include"template.h"
using namespace std;
leftistHeap::leftistHeap(leftistHeapNode *root):root(root) { }
leftistHeap::leftistHeapNode::leftistHeapNode(int x)
{
element = x; //赋值
left = right = nullptr; //左右孩子设为空
npl = 0; //零路径长初始化为0
}
leftistHeap::leftistHeapNode* leftistHeap::Merge(leftistHeapNode* h1, leftistHeapNode* h2)
{
if (!h1) return h2; //h1为空,返回h2
if (!h2) return h1; //h2为空,返回h1
if (h1->element > h2->element) { //维护h1的元素始终小于h2
leftistHeapNode* tmp = h2;
h2 = h1;
h1 = tmp;
}
if (!h1->left)h1->left = h2; //如果h1没有左孩子,让h2成为h1的左孩子
else { //如果h1有左孩子
h1->right = Merge(h1->right, h2); //合并h1的右孩子和h2
if (h1->left->nplright->npl)swapChild(h1);
//如果左式堆性质被破坏,即左孩子的零路径长小于右孩子,交换左右孩子
h1->npl = h1->right->npl + 1; //更新h1的零路径长
}
return h1;
}
const leftistHeap &merge(const leftistHeap &h1, const leftistHeap &h2)
{
//将返回值leftistHeapNode转换成leftistHeap,实现标准化接口
leftistHeap *ans=new leftistHeap(leftistHeap::Merge(h1.root, h2.root));
return *ans;
}
void leftistHeap::merge(const leftistHeap &h)
{
//调用已有merge
root = Merge(root, h.root);
}
void leftistHeap::insert(int x)
{
if (!root) { //不存在根节点,新建
root = new leftistHeapNode(x);
}
else { //否则,将新节点和原堆合并
leftistHeapNode *tmp = new leftistHeapNode(x);
root = Merge(root, tmp);
}
}
#include"heap.h"
#include"template.h"
using namespace std;
skewHeap::skewHeap(skewHeapNode* root):root(root) { }
skewHeap::skewHeapNode::skewHeapNode(int x)
{
element = x; //赋值
left = right = nullptr; //左右孩子都为空
}
skewHeap::skewHeapNode* skewHeap::Merge(skewHeapNode* h1, skewHeapNode* h2)
{
if (!h1) return h2; //h1为空,返回h2
if (!h2) return h1; //h2为空,返回h1
if (h1->element > h2->element) { //维护h1的元素始终小于h2
skewHeapNode* tmp = h2;
h2 = h1;
h1 = tmp;
}
if (!h1->left)h1->left = h2; //如果h1没有左孩子,让h2成为h1的左孩子
else {
h1->right = Merge(h1->right, h2); //合并h1的右孩子和h2
swapChild(h1); //交换孩子
}
return h1;
}
const skewHeap &merge(const skewHeap &h1, const skewHeap &h2)
{
//将返回值skewHeapNode转换成skewHeap,实现标准化接口
skewHeap* ans = new skewHeap(skewHeap::Merge(h1.root, h2.root));
return *ans;
}
void skewHeap::merge(const skewHeap &h)
{
//调用已有merge
root = Merge(root, h.root);
}
void skewHeap::insert(int x)
{
if (!root) {
root = new skewHeapNode(x);//不存在根节点,新建
}
else { //否则,将新节点和原堆合并
skewHeapNode *tmp = new skewHeapNode(x);
root = Merge(root,tmp);
}
}
main.cpp
#include"heap.h"
#include"template.h"
#include
#include
#include
using namespace std;
int main()
{
srand(unsigned(time(nullptr)));
int n = 10000;
int i;
int count = 0;
double sum1=0, sum2=0, sum3=0;//统计三个时间
chrono::time_point start,end;//开始,结束
chrono::duration seconds;//计时
while (n) { //n为测试数据大小
count++;
if (count == 100) { //计算100次后输出
printf("%d:\n%lf,%lf,%lf\n",n, sum1 , sum2 , sum3 );
count = 0;
n -= 1000; //测试数据减少1000
sum1 = 0.0, sum2 = 0.0, sum3 = 0.0; //更新sum为0
}
leftistHeap h1, h2, h3;
skewHeap h4, h5, h6;
heap h7(n), h8(n), h9(n);
int a[10002];
for (i = 0; i < n; i++) {
a[i] = 2 * i;
}
random_shuffle(a, a + n); //生成数据(偶数)
for (int i = 0; i < n; i++) { //生成第一棵树
h1.insert(a[i]);
h4.insert(a[i]);
h7.insert(a[i]);
}
for (i = 0; i < n; i++) {
a[i] = 2 * i + 1;
}
random_shuffle(a, a + n); //生成数据(奇数)
for (int i = 0; i < n; i++) { //生成第二棵树
h2.insert(a[i]);
h5.insert(a[i]);
h8.insert(a[i]);
}
//计算leftistHeap
start = chrono::high_resolution_clock::now();
h3 = merge(h1, h2);
end = chrono::high_resolution_clock::now();
seconds = end - start;
sum1 = sum1 + seconds.count();
//计算skewHeap
start = chrono::high_resolution_clock::now();
h6 = merge(h4, h5);
end = chrono::high_resolution_clock::now();
seconds = end - start;
sum2 = sum2 + seconds.count();
//计算heap
start = chrono::high_resolution_clock::now();
h9 = merge(h7, h8);
end = chrono::high_resolution_clock::now();
seconds = end - start;
sum3 = sum3 + seconds.count();
}
system("pause");
}