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<queue> #include<iostream> // 打印堆(左式堆,斜堆) 用于测试 // 层序遍历,按层输出 template<typename T> void print(T root) { if (!root)return; int cur = 1; int curnum = 1; int nextnum = 0; queue<T>q; //队列 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<typename T> void swapChild(T &h) { T tmp; tmp = h->right; h->right = h->left; h->left = tmp; } #endif
#include"heap.h" #include<queue> #include<cstdlib> #include<climits> #include<iostream> 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->npl<h1->right->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<algorithm> #include<cstdio> #include<chrono> 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<chrono::high_resolution_clock> start,end;//开始,结束 chrono::duration<double> 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"); }