最小堆。最大堆。

最大堆和最小堆是二叉堆的两种形式。

最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大。

最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小。




最小堆和最大堆的增删改相似,其实就是把算法中的大于改为小于,把小于改为大于。

生成最大堆:最大堆通常都是一棵完全二叉树,因此我们使用数组的形式来存储最大堆的值,从1号单元开始存储,因此父结点跟子结点的关系就是两倍的关系。

即:heap[father * 2] = heap[leftChild];  heap[father * 2 + 1] = heap[rightChild];


最大堆的初始化

在生成最大堆时,我们可以采取一次次遍历整棵树找到最大的结点放到相应的位置中。

但是这种方法有个不好的地方,就是每个结点都要重复比较多次。

所以我们可以换一种思考的顺序,从下往上进行比较。先找到最后一个有子结点的结点,先让他的两个子结点进行比较,找到大的值再和父结点的值进行比较。如果父结点的

值小,则子结点和父结点进行交换,交换之后再往下比较。然后一步步递归上去,知道所在结点的位置是0号位置跳出。这样就可以有效地减少比较所用到的时间。



但是每一次交换都要重复三步:heap[i] = temp; heap[i] = heap[j]; heap[j] = temp;

当树的结构比较大的时候,就会浪费很多时间。

所以我们可以先把父结点的值存到temp中跟子结点比较,如果子结点大的话就把子结点的值赋值给父结点,再往下比较,最后才把temp的值存到相应的位置。



	void Initialize(T a[], int size, int ArraySize)
	{
		delete []heap;
		isExist = false;
		heap = a;
		CurrentSize = size;
		MaxSize = ArraySize;
		//产生一个最大堆
		for(int i = CurrentSize / 2; i >= 1; i --)
		{
			T y = heap[i];			//子树的根
			//寻找放置y的位置
			int c = 2 * i; //c的父节点是y的目标位置
			while(c <= CurrentSize)
			{
				//heap[c]应是较大的同胞节点
				if(c < CurrentSize && heap[c] < heap[c + 1])
					c ++;
				//能把y放入heap[c / 2]吗?
				if(y >= heap[c])
					break;			//能				
				else			//不能
				{
					heap[c / 2] = heap[c];		//将孩子上移
					c *= 2;
				}			//下移一层
			}
			heap[c / 2] = y;
		}
	}


最大堆的插入

最大堆的插入的思想就是先在最后的结点添加一个元素,然后沿着树上升。跟最大堆的初始化大致相同。

MaxHeap<T> &Insert(const T&x)
	{	
		if(CurrentSize == MaxSize)
			exit(1);		//没有足够空间

		//为x寻找应插入位置
		//i从新的叶节点开始,并沿着树上升
		int i = ++ CurrentSize;
		while(i != 1 && x > heap[i/2])
		{
			//不把x放进heap[i]
			heap[i] = heap[i/2];		//元素下移
			i /= 2;		//移向父节点
		}
		heap[i] = x;		//这时候才把x放进去
		return *this;
	}

最大堆的删除

最大堆的删除,即删除最大的元素。我们先取最后的元素提到根结点,然后删除最大值,然后再把新的根节点放到合适的位置

MaxHeap<T> &DeleteMax(T &x)
	{
		//检查堆是否为空
		if(CurrentSize == 0)
			exit(1);		//队列空

		x = heap[1];		//最大元素
		T y = heap[CurrentSize--];		//最后一个元素
		//从根开始,重构大堆
		int i = 1, ci = 2;		//ci为i的儿子
		while(ci < CurrentSize)
		{
			if(ci < CurrentSize && heap[ci] < heap[ci + 1])			//比较两个子节点大小,取其大
				ci ++;
			//能否放y
			if(heap[ci] > y)		//不能
			{
				heap[i] = heap[ci];		//孩子上移
				i = ci;					//下移一层
				ci *= 2;
			}
			else			//能
				break;
		}
		heap[i] = y;
		return *this;
	}





  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值