左倾堆,也被称为左偏树、左偏堆、最左堆等。与二叉堆一样,它也是优先队列实现的方法。当涉及到对两个优先队列的合并时,左倾堆的效率比二叉堆的效率高很多。
template<class T>
class Node{
public:
T key;//键值
int npl;//零路径长度(Null Path Length)
Node *l;//左孩子
Node *r;//右孩子
Node(T key,Node *l,Node *r):key(key),npl(0),l(l),r(r){}
};
npl表示零距离长度:某结点到最近的不满结点的路径长度,不满结点是指最多只有一个孩子的结点。叶结点的npl=0,空结点的npl为-1。
//合并左倾堆x和左倾堆y
template<class T>
Node<T>* LeftistHeap<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->keykey
//将x的右孩子和y合并,合并后的树的根是x的右孩子
x->r=merge(x->r,y);
//如果x的左孩子为空,或者x的左孩子的npl<右孩子的npl,则交换x和y
if(!x->l||x->l->npl<x->r->npl)
{
Node<T> *tmp=x->l;
x->l=x->r;
x->r=tmp;
}
//设置合并后的新树的npl
if(x->r)
x->npl=x->r->npl+1;
else
x->npl=0;
return x;
}
template<class T>
void LeftistHeap<T>::merge(LeftistHeap<T> *other)
{
root=merge(root,other->root);
}
//添加
template<class T>
Node<T>* LeftistHeap<T>::insert(Node<T>* &heap,T key)
{
Node<T> *node=new Node<T>(key,NULL,NULL);
if(node)
return merge(root,node);
else
return heap;
}
template<class T>
void LeftistHeap<T>::insert(T key)
{
root=insert(root,key);
}
删除操作只在根结点出进行
//删除根结点
template<class T>
Node<T>* LeftistHeap<T>::remove(Node<T>* &heap)
{
if(!heap) return NULL;
Node<T> *l=heap->l;
Node<T> *r=heap->r;
delete heap;//删除根结点
return merge(l,r);//返回左右子树合并后的新树
}
template<class T>
void LeftistHeap<T>::remove()
{
root=remove(root);
}
#include
#include
using namespace std;
template<class T>
class Node{
public:
T key;//键值
int npl;//零路径长度(Null Path Length)
Node *l;//左孩子
Node *r;//右孩子
Node(T key,Node *l,Node *r):key(key),npl(0),l(l),r(r){}
};
template<class T>
class LeftistHeap{
private:
Node<T> *root;
public:
LeftistHeap();
~LeftistHeap();
void preOrder();//前序遍历
void inOrder();//中序遍历
void postOrder();//后序遍历
void merge(LeftistHeap<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);//合并
Node<T>* insert(Node<T>* &heap,T key);//将键值为key的结点插入左倾堆
Node<T>* remove(Node<T>* &heap);//删除根结点
void destroy(Node<T>* &heap);//销毁左倾堆
void print(Node<T>* heap,T key,int child);//打印左倾堆
};
//构造函数
template<class T>
LeftistHeap<T>::LeftistHeap()
{
root=NULL;
}
//析构函数
template<class T>
LeftistHeap<T>::~LeftistHeap()
{
destroy(root);
}
//前序遍历
template<class T>
void LeftistHeap<T>::preOrder(Node<T> *tree)
{
if(tree)
{
cout<<tree->key<<" ";
preOrder(tree->l);
preOrder(tree->r);
}
}
template<class T>
void LeftistHeap<T>::preOrder()
{
preOrder(root);
}
//中序遍历
template<class T>
void LeftistHeap<T>::inOrder(Node<T> *tree)
{
if(tree)
{
inOrder(tree->l);
cout<<tree->key<<" ";
inOrder(tree->r);
}
}
template<class T>
void LeftistHeap<T>::inOrder()
{
inOrder(root);
}
//后序遍历
template<class T>
void LeftistHeap<T>::postOrder(Node<T> *tree)
{
if(tree)
{
postOrder(tree->l);
postOrder(tree->r);
cout<<tree->key<<" ";
}
}
template<class T>
void LeftistHeap<T>::postOrder()
{
postOrder(root);
}
//交换两个结点的内容
template<class T>
void LeftistHeap<T>::swapNode(Node<T>* &x,Node<T>* &y)
{
Node<T> *tmp=x;
x=y;
y=tmp;
}
//合并左倾堆x和左倾堆y
template<class T>
Node<T>* LeftistHeap<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->keykey
//将x的右孩子和y合并,合并后的树的根是x的右孩子
x->r=merge(x->r,y);
//如果x的左孩子为空,或者x的左孩子的npl<右孩子的npl,则交换x和y
if(!x->l||x->l->npl<x->r->npl)
{
Node<T> *tmp=x->l;
x->l=x->r;
x->r=tmp;
}
//设置合并后的新树的npl
if(x->r)
x->npl=x->r->npl+1;
else
x->npl=0;
return x;
}
template<class T>
void LeftistHeap<T>::merge(LeftistHeap<T> *other)
{
root=merge(root,other->root);
}
//添加
template<class T>
Node<T>* LeftistHeap<T>::insert(Node<T>* &heap,T key)
{
Node<T> *node=new Node<T>(key,NULL,NULL);
if(node)
return merge(root,node);
else
return heap;
}
template<class T>
void LeftistHeap<T>::insert(T key)
{
root=insert(root,key);
}
//删除根结点
template<class T>
Node<T>* LeftistHeap<T>::remove(Node<T>* &heap)
{
if(!heap) return NULL;
Node<T> *l=heap->l;
Node<T> *r=heap->r;
delete heap;//删除根结点
return merge(l,r);//返回左右子树合并后的新树
}
template<class T>
void LeftistHeap<T>::remove()
{
root=remove(root);
}
//销毁左倾堆
template<class T>
void LeftistHeap<T>::destroy(Node<T>* &tree)
{
if(tree)
{
destroy(tree->l);
destroy(tree->r);
delete tree;
}
}
template<class T>
void LeftistHeap<T>::destroy()
{
destroy(root);
}
template<class T>
void LeftistHeap<T>::print(Node<T> *tree,T key,int child)
{
if(tree)
{
if(child==0)
cout<<tree->key<<"("<<tree->npl<<")"<<" is root"<<endl;
else
cout<<tree->key<<"("<<tree->npl<<")"<<" 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 LeftistHeap<T>::print()
{
if(root) print(root,root->key,0);
}