数据结构之左式堆的实现

  左式堆是一种很有意思的二叉树,他与二叉堆即优先队列一样,具有堆序性质,唯一的区别在于他并非完全的平衡,而是偏左的,对任意一个节点x,左儿子的零路径长至少与右儿子的零路径长一样大,所谓的零路径长是从x到一个不具有两个儿子的节点的最短路径长:

 如下:



只有左边的才是左式堆,因为左树的左儿子与右儿子的零路径长一样大,右边的不是左式堆,因为1*的左儿子的零路径长为0,而右儿子的零路径长为1,

下面就是一个很好的左式堆:

左式堆虽然没有完全二叉堆那么平衡,但是可以证明,他对于插入,删除与查找最小值与完全二叉堆是一个级别的,更重要的是他能有效的支持堆的合并操作,两个堆的合并

他能做到O(log(n)),这是完全二叉堆所没有的。

左式堆的实现难点在于合并操作,只要实现了合并操作,插入与删除都可以用合并操作实现,下面就是我的C++代码实现:


//leftheap.h

#ifndef LEFTHEAP_H
#define LEFTHEAP_H
template<class Comparable>
class leftheap
{
	public:
		leftheap(){root=NULL;}
		leftheap(const leftheap &rhs)
		{
		  this=rhs;
		}
               ~leftheap()
		{
			if(root!=NULL)
				makeEmpty(root);
		}
               leftheap & operator =(const leftheap &rhs)
		{
			if(this!=&rhs)
                          root=clone(rhs.root);
			return *this;
		}
		bool isEmpty()const
		{
			return root==NULL;
		}
		const Comparable & findMin()const
		{
			return root->element;
		}
		void insert(const Comparable x)
		{
			root=merge(new leftheapNode(x),root);
		}
               void deleteMin()
		{
			if(!isEmpty())
			{
				leftheapNode *old=root;
				root=merge(root->left,root->right);
				delete old;
			}
		}
		void deleteMin(Comparable &x)
		{
			x=findMin();
			deleteMin();
		}
		void makeEmpty()
		{
			makeEmpty(root);
		}
		void merge(leftheap &rhs)
		{
			if(this==&rhs)
				return;
			root=merge(root,rhs.root);
			rhs.root=NULL;
		}
		void print()
		{
			print(root);
		}


	private:
		struct leftheapNode
		{
			Comparable element;
			leftheapNode *left;
			leftheapNode *right;
			int npl;
		    leftheapNode(const Comparable &ele,leftheapNode *lt=NULL,leftheapNode *rt=NULL,int x=0)
			   :element(ele),left(lt),right(rt),npl(x){}
		};
			leftheapNode *root;
			
		leftheapNode *merge(leftheapNode *h1,leftheapNode *h2 )
		{
			if(h1==NULL)
				return h2;
			if(h2==NULL)
				return h1;
			if(h1->element<h2->element)
				return merge1(h1,h2);
			else
				return merge1(h2,h1);
		}

               leftheapNode *merge1(leftheapNode *h1,leftheapNode *h2 )
		{
			if(h1->left==NULL)
				h1->left=h2;
			else
			{
				h1->right=merge(h1->right,h2);
				if(h1->left->npl<h1->right->npl)
					swapChildren(h1);
				h1->npl=h1->right->npl+1;
			}
			return h1;
		}
		void swapChildren(leftheapNode *h1)
		{
			if(h1!=NULL)
			{
			leftheapNode *h=h1->left;
			h1->left=h1->right;
			h1->right=h;
			}
		}
		void makeEmpty(leftheapNode *h)
		{       
			if(h==NULL)
				return;
	          
			makeEmpty(h->left);
			makeEmpty(h->right);
			delete h;
		}
		void print(leftheapNode * t,int i=0)const
		{
           	if(t!=NULL)
			{
			  	print(t->left,i+1);
				for(int j=0;j<i;j++)
			       cout<<"  "; 
				cout<<t->element<<endl;
				
				print(t->right,i+1);
			}
		}
		leftheapNode *clone(leftheapNode *t)
		{
			if(t==NULL)
				return NULL;
			return new leftheapNode(t->element,clone(t->left),clone(t->right),t->npl);
		}

	};

#endif


//main.cpp


#include<iostream>
#include<cstdio>
using namespace std;
#include"leftheap.h"
int main()
{
freopen("out.txt","w",stdout);
leftheap<int> LH;
int min;
for(int i=0;i<150;i++)
LH.insert(i);
for(int i=0;i<100;i++)
{
    LH.deleteMin(min);
    cout<<min<<" ";
}
cout<<endl;
LH.print();
cout<<endl;
fclose(stdout);
return 0;

}


输出结果为:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 
        141
      119
        142
    107
        131
      124
        132
  102
          137
        121
          138
      111
          127
        126
          128
    103
            133
          123
              148
            134
        116
          147
      112
100
        114
      110
          149
        115
    104
              139
            120
                146
              140
          117
              129
            125
                145
              130
        113
      105
                135
              122
                  144
                136
            118
              143
          109
        106
  101
    108
可以看到,他的确是具有堆序性质,而且还是很平衡的,还有,我的main函数虽然没有测试merge操作,但其实插入与删除我都是用merge操作实现的,所以没什么问题!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值