堆的建立、插入与删除

堆的储存结构

堆使用完全二叉树的结构进行储存,根据完全二叉树的性质,在堆中给定下标为i的节点时:

  1. 如果i=0,节点i是根节点;否则节点i的父节点为节点(i-1)/2
  2. 如果2i+1>n-1,则节点i无左子女;否则节点i的左子女为2i+1
  3. 如果2i+2>n-1,则节点i无右子女;否则节点i的右子女为2i+2

堆元素使用的结构体定义

typedef struct Message {
	char Msg[20];     //命令名称
	int K;            //优先级
	friend bool operator>(Message& A, Message& B);
	friend bool operator<=(Message& A, Message& B);
}E;

MinHeap的类成员

#define DefaultSize 100000
class MinHeap
{
private:
	E* heap;           //存放最小堆中元素的数组
	int currentSize;   //最小堆中当前元素数量
	int maxHeapSize;   //最小堆能容纳的最大数量

public:
	MinHeap(int sz = DefaultSize);                    //构造函数
	~MinHeap() { delete[] heap; } //析构函数
	bool Insert(const E& x);      //将x插入到最小堆中
	bool Remove(E& x);            //删除堆顶元素,并通过x返回

private:
	void siftDown(int start, int m);     //从start到m下滑调整成为最小堆
	void siftUp(int start);              //从start到0向上调整成为最小堆
};

MinHeap的成员函数

1.构造函数,创建一个sz大小的数组空间,初始化数组大小为0,通过插入操作对堆进行赋值

MinHeap::MinHeap(int sz)
{
	//动态建立数组空间
	maxHeapSize = ( DefaultSize < sz) ? sz : DefaultSize;
	heap = new E[maxHeapSize];     //创建储存空间
	if (heap == NULL) {
		cerr << "储存分配失败" << endl; exit(1);
	}
	currentSize = 0;               //建立当前大小
}

2.siftdown函数

void MinHeap::siftDown(int start, int m)
{
	//从节点start开始到m为止,自上向下比较,如果子女的值小于父节点的值
	//则关键码小的上浮,继续向下层比较,这样将一个集合局部调整为最小堆
	int i = start, j = i * 2 + 1;     //j是i的左子女
	E temp = heap[i];                 //将start中的元素存放到临时空间中
	while (j <= m) {
		if (j<m && heap[j]>heap[j + 1]) {
			j++;                      //如果右子树比左子树小,则将j指向右子树
		}
		if (temp <= heap[j]) break;   //如果根节点比子女小,则不做调整
		else {
			heap[i] = heap[j];        //否则小的上移
			i = j;
			j = j * 2 + 1;            //i,j下移
		}
	}
	heap[i] = temp;                   //回放temp中暂存的元素
}

3.siftup函数

void MinHeap::siftUp(int start)
{
	//从节点start开始向0调整,自下而上比较,如果子女的值小于父节点的值
	//则交换,小的上移,这样将集合调整为最小堆
	int j = start;
	int i = (j - 1) / 2;               //i是j的父节点
	E temp = heap[j];
	while (j > 0) {                    //沿父节点路径向上直达根
		if (heap[i] <= temp) break;    //父节点的值小,不作调整
		else {
			heap[j] = heap[i];         //父节点的值大,用父节点的值替代子女节点的值
			j = i; i = (i - 1) / 2;    //i,j上移
		}
	}
	heap[j] = temp;                    //回送
}

4.MinHeap的插入函数

bool MinHeap::Insert(const E& x)
{
	//将x插入到最小堆中
	if (currentSize == DefaultSize) {
		cerr << "Heap Full" << endl; return false;  //堆满
	}            
	heap[currentSize] = x;        //插入
	siftUp(currentSize);          //向上调整
	currentSize++;                //堆计数加1
	return true;
}

5.MinHeap的删除函数

bool MinHeap::Remove(E& x)
{
	if (!currentSize) {
		//cout << "Heap empty" << endl;
		return false;                             //堆空
	}
	x = heap[0]; heap[0] = heap[currentSize - 1]; //返回并删除堆顶元素,用最后一个元素填补根节点
	currentSize--;                                //最小堆计数减1
	siftDown(0, currentSize - 1);                 //自上而下调整最小堆
	return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值