aspglujalk优先队列(堆及堆排序)

堆ADT

堆是一种类似于完全二叉树的结构。堆可以用完全二叉树的图来表示,但是堆通常来说都是由数组来进行构建的。相较于指针传输,数组下标传输更快,因此通过构建最小堆和最大堆就能够快速找到最小或最大最优先的元素。唯一的问题在于堆的最大高度要提前确定。

1.堆的性质

最小堆:在一个堆中,对于每一个结点X,X的父节点的data小于X的data,X的data小于任一子结点的data。
最大堆:在一个堆中,对于每一个结点X,X的父节点的data大于X的data,X的data大于任一子结点的data。
(根节点除外)

2.建一个最小二叉堆

----------------------------------------------------堆的框架及接口---------------------------------------------------
#include<queue>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

template<typename T>
class BinaryHeap
{
public:
	explicit BinaryHeap(int capacity=100);
	explicit BinaryHeap(const vector<T>& items);
	bool isEmpty()const;
	const T& FindMin()const;
	void Insert(const T& data);
	void DeleteMin();
	void DeleteMin(T& minItem);
	void MakeEmpty();
	int currentsize;
	
	~BinaryHeap()
	

private:
	vector<T> array;
	void BuildHeap();
	void PercolateDown(int hole);
	
};

通过使用stl函数vector建立可变容量数组

----------------------------------------------------构造函数---------------------------------------------------------
template<typename T>
BinaryHeap<T>::BinaryHeap(const vector<T>& items) :array(items.size() + 10), currentsize(items.size())
{
	for (int i = 0; i < items.size(); i++)
	{
		array[i + 1] = items[i];
		BuildHeap;
	}
}

template<typename T>
void BinaryHeap<T>::BuildHeap()
{
	for (int i = currentsize/2; i >0; i--)
	{
		PercolateDown(1);
	}
}

插入堆

template<typename T>
void BinaryHeap<T>::Insert(const T& data)
{
	if (currentsize ==array.size()-1)
	{
		array.resize(array.size() * 2);
	}
	int hole = ++currentsize;
	for ( ;hole>1&&data<array[hole/2]; hole/2)
	{
		array[hole] = array[hole / 2];
		array[hole] = data;
	}
}

删除最小

template<typename T>
void BinaryHeap<T>::DeleteMin()
{
	if (isEmpty())
	{
		throw underflowException;
		array[1] = array[currentsize--];
		PercolateDown(1);
	}
}

template<typename T>
void BinaryHeap<T>::DeleteMin(T& minitem)
{
	if (isEmpty())
	{
		throw underflowException;
		minitem = array[1];
		array[1] = array[currentsize--];
		PercolateDown(1);
	}
}

渗滤percolate down

template<typename T>
void BinaryHeap<T>::PercolateDown(int hole)
{
	int child;
	T tmp = array[hole];
	for ( ;  hole*2< currentsize;hole=child)
	{
		child = hole * 2;
		if (child!=currentsize&&array[child+1]<array[child])
		{
			child++;
		}
		if (array[child]<tmp)
		{
			array[hole] = array[child];
		}
		else
		{
			break;
		}
		array[hole] = tmp;
	}
}

3.优先队列的应用

null

4.d堆

相较于二叉堆,d堆所有的子结点都有d个儿子。
d堆的insert运行时间更短为log_d(N),但是delete运行时间更长为dlog_d(N).
在实践中4堆可以胜过二叉堆。
一个d堆

普通的堆难以实行合并merge的操作,实行merge操作繁琐且运行时间过长。以下几种特殊堆可以执行merge。

5.左式堆

左式堆也是二叉树,与二叉堆唯一区别是左式堆非常不平衡。

零路径长(null path length):从X到不具有两个儿子结点特征的结点的最短路径长。具有0/1个儿子结点npl=0,npl(NULL)=-1。

左式堆:对于每一个结点X,左儿子的npl大于等于右孩子的npl。

#include<iostream>

template<typename T>
class LeftistHeap
{
public:
	LeftistHeap();
	LeftistHeap(const LeftistHeap& rhs);
	~LeftistHeap();
	bool isEmpty()const;
	const T& findMin()const;
	void insert(const T& x);
	void deleteMin();
	void deleteMin(T& minItem);
	void makeEmpty();
	void merge(LeftistHeap& rhs);
	const LeftistHeap& operator=(const LeftistHeap& rhs);

private:
	struct LeftistNode
	{
		T element;
		LeftistNode* leftchild;
		LeftistNode* rightchild;
		int npl;

		LeftistNode(const T&theElement,LeftisNode*lt=NULL,LeftisNode*rt=NULL,int np=0):element(theElement),leftchild(lt),rightchild(rt),npl(np){ }
	};

	LeftistNode* root;
	LeftistNode* merge(LeftisNode* h1, LeftisNode* h2)
	{
		if (h1==NULL)
		{
			return h2;
		}
		if (h2==NULL)
		{
			return h1;
		}
		if (h1->element<h2->element)
		{
			return merge1(h1, h2);
		}
		if (h1->element>h2->element)
		{
			return merge1(h2, h1);
		}
	}

	LeftistNode* merge1(LeftisNode* h1, LeftisNode* h2)
	{

		if (h1->leftchild == NULL)
		{
			h1->left = h2;
		}
		else
		{
			h1->rightchild = merge(h1->rightchild, h2);
			if (h1->leftchild->npl < h1->rightchild->npl)
			{
				swapChildren(h1);
				h1->npl = h1->right->npl + 1;
			}
		}
		retrun h1;
	}
	void swapChildren(LeftistNode* t);
	void reclaimMemory(LeftisNode* t);
	LeftistNode* clone(LeftisNode* t) const;
};

template<typename T>
LeftistHeap<T>::LeftistHeap()
{
	LeftisNode<T>* p;
	T data;
	cin >> data;
	if (data==NULL)
	{
		p = null;
	}
	else
	{
		p = new LeftisNode<T>();
		if (p==NULL)
		{
			cout << "false";
			exit(1);
		}
	}
	p->element = data;
	p->leftchild = NULL;
	p->rightchild =NULL

}

template<typename T>
LeftistHeap<T>::LeftistHeap(const LeftistHeap& rhs)
{

}


template<typename T>
LeftistHeap<T>::~LeftistHeap()
{
	reclaimMemory();
}

template<typename T>
inline void LeftistHeap<T>::insert(const T& x)
{
	root = merge(new LeftistNode(x), root);
}

template<typename T>
void LeftistHeap<T>::swapChildren(LeftistNode* t)
{
	LeftistNode<T>* AUX;
	AUX = t->rightchild;
	t->rightchild = t->leftchild;
	t->leftchild = AUX;
	return t;
}

template<typename T>
void LeftistHeap<T>::merge(LeftistHeap& rhs)
{
	if (this==&rhs)
	{
		return;
	}
	root = merge(root, rhs.root);
	rhs.root = NULL;
}

template<typename T>
void LeftistHeap<T>::deleteMin(T& minItem)
{
	minItem = findMin();
	deleteMin();
}

6.斜堆

7.二项队列

一个二项队列是堆序的树的集合。堆序中的每一棵树都是被约束的二项树。高度为k的二项树将通过一棵二项树k-1连接到另一棵二项树的根上。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值