• 二叉堆


    前言

    其实这东西学过两年了……所以应该算是复习笔记吧?

    定义

    二叉堆,简称堆,顾名思义,是一棵二叉树,还是一棵完全二叉树。其显著特征是整棵树中父结点的值与子结点的值的大小关系都相同(即父结点的值均大于两个子结点的值或均小于两个子结点的值)。若大于,称之为大根堆,小于则是小根堆。显而易见,堆顶元素(即根节点)为二叉堆的最大或最小元素。在存储的时候,为了方便,我们可以将整个二叉堆存到一个数组里,以1为根结点,某一元素两个儿子的下标分别为(2i)和(2i+1),父亲下标为(i/2)。

    用途

    二叉堆可用于维护一个序列的极值。它支持插入一个元素,删除极值元素和查询极值元素。通过拼接两个二叉堆,我们还可以对删除指定元素的操作。

    操作实现

    插入

    首先将元素插入二叉堆的最后,接着不断与它的父结点比较,若不满足堆的顺序则交换它与它的父结点,直到整个二叉堆重新满足二叉堆的性质(即到达堆顶或当前比较结果满足堆的顺序)。

    void insert(const Type &x)
    {
    	a[++size]=x;
    	unsigned int now=size;
    	while(now>1&&!compare(a[now>>1],a[now]))
    	{
    		swap(a[now>>1],a[now]);
    		now>>=1;
    	}
    	return;
    }
    

    查询堆顶元素

    直接返回根节点即可。

    inline Type top(){return a[1];}
    

    删除堆顶元素

    首先将堆顶元素与最后一个元素交换位置,并维护堆的大小(将堆的大小减一),则原来的堆顶元素已被删去。接下来我们要维护堆的性质,从堆顶元素开始,不断把当前元素与较小儿子(大根堆为较大)进行比较,若不满足堆的顺序则交换,直到整个二叉堆重新满足堆的性质(即到达末尾或当前比较结果满足堆的顺序)。

    void erase()
    {
    	a[1]=a[size];
    	--size;
    	unsigned int now=1;
    	while(now<<1<=size)
    	{
    		unsigned int t=now<<1;
    		if((t|1)<=size&&compare(a[t|1],a[t]))
    			t|=1;
    		if(compare(a[now],a[t]))
    			break;
    		swap(a[now],a[t]);
    		now=t;
    	}
    	return;
    }
    

    删除指定元素(拓展)

    以上就是普通二叉堆的所有操作。但有时候我们面临的问题涉及到从堆当中删除某一特定值的元素,这可以使用两个二叉堆拼接起来解决。我们建立一个辅助二叉堆,二叉堆使它的排序方式与需要维护的二叉堆相同。显然,当某一元素不是原二叉堆的堆顶元素时,它的存在与否对正确性并无影响,因此我们可以等到它变为堆顶元素时再删掉它。而辅助二叉堆就是用来保存尚未删除的数的序列的。每次遇到删除操作时,我们先将要删除的元素存入辅助二叉堆。等到取堆顶元素的操作时,我们不断查看原二叉堆的堆顶元素是否与辅助二叉堆相等,若是则同时删除两个二叉堆的堆顶元素,直到原二叉堆的堆顶元素与辅助二叉堆的堆顶元素不相等。易证,当某一元素成为原二叉堆的堆顶元素时,比它小(大根堆为大)的元素均已被删除,意即比它大的元素也不会存在于辅助二叉堆中,从而只有当辅助二叉堆中的堆顶元素等于原二叉堆时需要删除,故这一算法正确。

    inline Type top()
    {
    	while(!a.empty()&&!t.empty()&&a.top()==t.top())
    	{
    		a.erase();
    		t.erase();
    	}
    	return a.top();
    }
    inline void insert(const Type &x){a.insert(x);return;}
    inline void erase(const Type &x){t.insert(x);return;}
    

    总代码

    BasicHeap即为不带删除指定元素操作的基本堆,Heap为带这一操作的堆。

    #ifndef _HEAP_HPP_
    #define _HEAP_HPP_
    
    template<typename Type>
    class BasicHeap
    {
    	private:
    		static const unsigned int maxn=500000;
    		Type a[maxn+1];
    		unsigned int size;
    		bool (*compare)(const Type &a,const Type &b);
    		static inline bool less(const Type &a,const Type &b){return a<b;}
    		static inline void swap(Type &a,Type &b){a^=b;b^=a;a^=b;return;}
    	public:
    		BasicHeap(bool (*judge)(const Type &a,const Type &b)=less):size(0),compare(judge){}
    		BasicHeap(const BasicHeap<Type> &b)
    		{
    			size=b.size;
    			for(unsigned int i=1;i<=size;++i)
    				a[i]=b.a[i];
    		}
    		inline Type top()const{return a[1];}
    		inline bool empty()const{return size==0;}
    		void insert(const Type &x)
    		{
    			a[++size]=x;
    			unsigned int now=size;
    			while(now>1&&!compare(a[now>>1],a[now]))
    			{
    				swap(a[now>>1],a[now]);
    				now>>=1;
    			}
    			return;
    		}
    		void erase()
    		{
    			a[1]=a[size--];
    			unsigned int now=1;
    			while(now<<1<=size)
    			{
    				unsigned int t=now<<1;
    				if((t|1)<=size&&compare(a[t|1],a[t]))
    					t|=1;
    				if(compare(a[now],a[t]))
    					break;
    				swap(a[now],a[t]);
    			}
    		}
    };
    template<typename Type>
    class Heap
    {
    	private:
    		BasicHeap<Type>a,t;
    		static inline bool less(const Type &a,const Type &b){return a<b;}
    	public:
    		Heap(bool(*judge)(const Type &a,const Type &b)=less):a(judge),t(judge){}
    		Heap(const Heap &b):a(b.a),t(b.t){}
    		inline Type top()
    		{
    			while(!a.empty()&&!t.empty()&&a.top()==t.top())
    			{
    				a.erase();
    				t.erase();
    			}
    			return a.top();
    		}
    		inline bool empty()const{return a.empty();}
    		inline void insert(const Type &x){a.insert(x);return;}
    		inline void erase(const Type &x){t.insert(x);return;}
    };
    
    #endif
    
  • 相关阅读:
    团队冲刺第五天
    团队冲刺第一天
    IOS开发(四):开关控件UISwitch
    IOS开发(七):UIActionSheet和UIAlertView
    IOS开发(五):分段控件UISegmentedControl
    [转]IOS开发(一):第一个有交互的APP
    [转]IOS开发(三):UIImageView、UISlider、UIStepper、UIButton
    IOS开发(八):系统声音服务
    [转]Tab Bars和Pickers
    [转]IOS开发(二):ImageView、TextField、键盘
  • 原文地址:https://www.cnblogs.com/Psephurus-Gladius-zdx/p/12289214.html
Copyright © 2020-2023  润新知