左式堆 斜堆

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

tmplate.h

#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

heap.cpp

#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;
}

letist heap.cpp

#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);
	}
}

skewheap.cpp

#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");
}

 
  

你可能感兴趣的:(数据结构与算法分析)