首页 > 编程知识 正文

小根堆和最小堆,大根堆和小根堆解

时间:2023-05-05 14:37:54 阅读:267752 作者:869

1.什么是大根堆、现实的水池堆?

首先堆应该是一颗完全二叉树,大根堆就是二叉树的所有父节点的值都比左右孩子的值大,现实的水池相反。下面是大根堆和现实的水池堆的图:

如上,左图是一个大根堆,右图是一个现实的水池堆。

2.树的数组存储

我们可以将树存储在一个数组中:

根结点存储在位置0,根的左孩子存储在位置1,右孩子存储在位置2。由此可以得出如下公式:

如果父节点的位置为i,那么他的左孩子和右孩子的位置分别为2*i+1和2*i+2。

如果一个结点的位置为i,那么他的父节点的位置为(i-1)/2;

3.大根堆现实的水池堆的操作

由于大根堆和现实的水池堆的操作基本相同,只是结点比较的方式不一样,一个取大,一个取小。我们在这里以大根堆为例。

3.1大根堆的插入操作

如上,我们在大根堆中插入一个元素45,首先先将元素插入在树的右下角(数组的末尾),然后将45与其父节点23比较,发现它比23大,将45与23交换,然后再将45与其新的父节点32比较,发现还比32大,再交换位置,再与54比较,发现比54小,位置不变,插入完成。

3.2大根堆的删除操作

首先大根堆只能删除根节点,另外,为了保证堆是一颗完全二叉树的特性,我们将树的右下角的元素赋值给根节点,然后将右下角节点删除(在数组中:将第一个元素删除,将最后一个元素赋值给第一个元素,将最后一个位置删除),然后调整二叉树。

如上图:我们要删除55,将右下角元素0赋值给55(也可以交换,然后不用管最后一个结点),这时根结点变为0,左后孩子分别为54和12,取左右孩子的最大值:54,54>0,将0和54交换位置,这时它的左右孩子变为44和23,取最大孩子44,44>0,交换位置,重复上述操作,直至0比它的左右孩子的值都大,或者没有左右孩子。

3.3代码实现 template<typename type>class MaxHeap{public://插入操作void Insert(type e){//将新添加的结点插入到队尾_maxHeap.push_back(e);//得到自己和父节点的索引int selfIndex = _maxHeap.size() - 1;int fatherIndex = (selfIndex - 1) / 2;//将新插入的元素放入到合理的位置while (fatherIndex >= 0 && selfIndex != 0){if (_maxHeap[fatherIndex] >= e)break;_maxHeap[selfIndex] = _maxHeap[fatherIndex];selfIndex = fatherIndex;fatherIndex = (fatherIndex - 1) / 2;}_maxHeap[selfIndex] = e;}//删除操作void Delete(){//删除堆顶元素if (!_maxHeap.empty()){cout << "删除了堆顶元素:" << _maxHeap[0] << endl;//将末尾元素赋值给堆顶_maxHeap[0] = _maxHeap[_maxHeap.size() - 1];//将末尾元素删除_maxHeap.pop_back();}//从上到下对堆进行调整Adjust();}void Adjust(){if (_maxHeap.empty())return;//堆顶元素type topEle = _maxHeap[0];int fatherIndex = 0;int childIndex = fatherIndex * 2 + 1;while (childIndex < _maxHeap.size()){//如果右孩子也存在,指向左右孩子中较大的结点if (childIndex + 1 < _maxHeap.size() && _maxHeap[childIndex] < _maxHeap[childIndex + 1])childIndex++;if (_maxHeap[childIndex] <= topEle)break;_maxHeap[fatherIndex] = _maxHeap[childIndex];fatherIndex = childIndex;childIndex = childIndex * 2 + 1;}_maxHeap[fatherIndex] = topEle;}void Show(){for (auto ele : _maxHeap){cout << ele << ends;}cout << endl;}private:vector<type> _maxHeap;};

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。