斜堆【数据结构】

                                                           斜堆

一、介绍

斜堆,也称为自适应堆,它是左倾堆的一个变种。与左倾堆一样,它通常也用于优先队列的实现,它的合并操作的时间复杂度也是O(logn)

斜堆的结点

template<class T>
class Node{
	public:
		T key;//键值 
		Node *l;//左孩子 
		Node *r;//右孩子 
		Node(T key,Node *l,Node *r):key(key),l(l),r(r){}
};

二、分析

1、合并操作

空斜堆和非空斜对进行合并,返回非空斜堆

两个非空斜堆进行合并,取较小堆的根结点为新的根结点,将较小堆的根结点的右孩子和较大堆进行合并

合并后直接交换新堆的根结点的左孩子和右孩子

//合并斜堆x和斜堆y 
template<class T>
Node<T>* SkewHeap<T>::merge(Node<T>* &x,Node<T>* &y)
{
	if(!x) return y;
	if(!y) return x;
	//合并x,y时,将x作为合并后的树的根
	if(x->key>y->key)
	  swapNode(x,y);//保证x->key<y->key
	//将x的右孩子和y合并,合并后直接交换左右孩子 
	Node<T>* tmp=merge(x->r,y);
	x->r=x->l;
	x->l=tmp;
	return x;
}

三、C++实现

#include<iostream>
#include<algorithm>
 
using namespace std;
 
template<class T>
class Node{
	public:
		T key;//键值 
		Node *l;//左孩子 
		Node *r;//右孩子 
		Node(T key,Node *l,Node *r):key(key),l(l),r(r){}
};
 
template<class T>
class SkewHeap{
	private:
		Node<T> *root;
	public:
		SkewHeap();
		~SkewHeap();
		void preOrder();//前序遍历 
		void inOrder();//中序遍历 
		void postOrder();//后序遍历 
		void merge(SkewHeap<T> *other);//合并 
		void insert(T key);//将键值为key的结点插入斜堆 
		void remove();//删除根结点结点 
		void destroy();//销毁斜堆
		void print();//打印斜堆 
		
	private:
		void preOrder(Node<T> *heap);//前序遍历
		void inOrder(Node<T> *heap);//中序遍历 
		void postOrder(Node<T> *heap);//后序遍历 
		void swapNode(Node<T>* &x,Node<T>* &y);//交换结点 
		Node<T>* merge(Node<T>* &x,Node<T>* &y);//合并
		void destroy(Node<T>* &heap);//销毁斜堆 
		void print(Node<T>* heap,T key,int child);//打印斜堆 
};
 
//构造函数
template<class T>
SkewHeap<T>::SkewHeap()
{
	root=NULL;
}
 
//析构函数
template<class T>
SkewHeap<T>::~SkewHeap()
{
	destroy(root);
} 
 
//前序遍历
template<class T>
void SkewHeap<T>::preOrder(Node<T> *tree)
{
	if(tree)
	{
		cout<<tree->key<<" ";
		preOrder(tree->l);
		preOrder(tree->r); 
	}
} 
 
template<class T>
void SkewHeap<T>::preOrder()
{
	preOrder(root);
}
 
//中序遍历 
template<class T>
void SkewHeap<T>::inOrder(Node<T> *tree)
{
	if(tree)
	{
		inOrder(tree->l);
		cout<<tree->key<<" ";
		inOrder(tree->r);
	}
}
 
template<class T>
void SkewHeap<T>::inOrder()
{
	inOrder(root);
}
 
//后序遍历
template<class T>
void SkewHeap<T>::postOrder(Node<T> *tree)
{
	if(tree)
	{
		postOrder(tree->l);
		postOrder(tree->r);
		cout<<tree->key<<" ";
	}
}
 
template<class T>
void SkewHeap<T>::postOrder()
{
	postOrder(root);
}
 
//交换两个结点的内容
template<class T>
void SkewHeap<T>::swapNode(Node<T>* &x,Node<T>* &y)
{
	Node<T> *tmp=x;
	x=y;
	y=tmp;
} 
 
//合并斜堆x和斜堆y 
template<class T>
Node<T>* SkewHeap<T>::merge(Node<T>* &x,Node<T>* &y)
{
	if(!x) return y;
	if(!y) return x;
	//合并x,y时,将x作为合并后的树的根
	if(x->key>y->key)
	  swapNode(x,y);//保证x->key<y->key
	//将x的右孩子和y合并,合并后直接交换左右孩子 
	Node<T>* tmp=merge(x->r,y);
	x->r=x->l;
	x->l=tmp;
	return x;
}
 
template<class T>
void SkewHeap<T>::merge(SkewHeap<T> *other)
{
	root=merge(root,other->root);
}
 
//添加
template<class T>
void SkewHeap<T>::insert(T key) 
{
	Node<T> *node=new Node<T>(key,NULL,NULL);
	if(node) root=merge(root,node);  
}
 
//删除根结点
template<class T>
void SkewHeap<T>::remove()
{
	if(!root) return NULL;
	Node<T> *l=root->l;
	Node<T> *r=root->r;
	delete root;//删除根结点
	root=merge(l,r);//返回左右子树合并后的新树 
}
 
//销毁斜堆
template<class T>
void SkewHeap<T>::destroy(Node<T>* &tree)
{
	if(tree)
	{
		destroy(tree->l);
		destroy(tree->r);
		delete tree;
	}
} 
 
template<class T>
void SkewHeap<T>::destroy()
{
	destroy(root);
}
 
template<class T>
void SkewHeap<T>::print(Node<T> *tree,T key,int child)
{
	if(tree)
	{
		if(child==0)
		  cout<<tree->key<<" is root"<<endl;
		else
		  cout<<tree->key<<" is "<<key<<"'s "<<(child==1?"left child":"right child")<<endl;
		print(tree->l,tree->key,1);
		print(tree->r,tree->key,-1);
	}
}
 
template<class T>
void SkewHeap<T>::print()
{
	if(root) print(root,root->key,0);
}

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/85221506