大根堆、小根堆(数组模拟操作)

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;
};
发布了124 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42214953/article/details/104900781