堆储存方式及堆操作

630 阅读1分钟

堆的定义

堆是一个树型的数据结构,是一个二叉树,每个节点都比他的字节的小(小根堆)/大(大根堆)。

堆的存储方式

由于堆是一个满二叉树,所以可以使用数组的方式进行存储,如图我们可以观察到,如果当前节点的下标是i,则父节点为i / 2,子节点为 i * 2和i * 2 +1;这样每个节点就可找到父节点和子节点。

图解

堆.png

堆的操作

堆主要包含5个操作:

  1. 判断对是否为空:empty();
  2. 返回堆的大小:size();
  3. 往队中加入元素:push();
  4. 返回堆头元素:top();
  5. 删除堆头袁术:pop();

实现堆的操作:

class heap //小根堆
{
	protected:
		int n;//表示堆中的元素个数 
		int h[N];
	public:	
		int size()
		{
			return n;
		}
		int empty()
		{
			return n==0;
		}
		void down(int u)//将以u为根节点的树变成推 ,使用前提是:左右子树都是推。 
		{
			int t=u;
			if(u*2<=n&&h[u*2]<h[t]) t=u*2;
			if(u*2+1<=n&&h[u*2+1]<h[t]) t=u*2+1;//先在当前节点和左右节点中找到最小的节点
			if(t!=u)//如果最小的节点为子节点
			{
				swap(h[t],h[u]);//交换两个节点
				down(t);//由于子节点的值发生变化,所以需要将子节点的子树转化为堆。 
			} 
		}
		void up(int u)
		{
			while(u/2>=1&&h[u/2]>h[t]) //如果父节点比当前节点小 
			{
				swap(h[t],h[u]);//交换两个节点 
				u>>=1;//父节点继续操作 
			}
		 } 
		int push(int x)
		{
			h[++n]=x;
			up(n); 
		} 
		int top()
		{
			return h[1];
		}
		void pop()
		{
			h[1]=h[n--];
			down(1);
		}
}