二叉堆

  • 二叉堆

定义:二叉堆是完全二叉树或近似完全二叉树。
二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,
且每个节点的左子树和右子树都是一个二叉堆。
它分为两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

最大堆示意图,数组中的存储形式在下面

 

  • 插入

插入的数值先放在堆的最后,然后与其父节点进行比较交换

  • 删除

用最后的数值来替换需要删除的数值,然后与其子节点中最大的值比较交换

 

//MaxHeap.h
#pragma once

/*
二叉堆
定义:二叉堆是完全二叉树或近似完全二叉树。
二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,
且每个节点的左子树和右子树都是一个二叉堆。
它分为两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
*/

#include <iostream>
template <typename T>
class MaxHeap
{
public:
	MaxHeap(int data):capacity(data), m_num(0), pHeap(nullptr)
	{
		pHeap = new T[capacity];
		memset(pHeap, 0, sizeof(T) * capacity);
	}
	~MaxHeap()
	{
		if (pHeap != nullptr)
		{
			delete pHeap;
			pHeap = nullptr;
		}
	}
	void Insert(T data);//插入
	void Delete(T data);//删除
	void Print();		//打印
	void InsertAmend(int index);//插入修正,调整为最大堆
	void DeleteAmend(int index);//删除修正,调整为最大堆
private:
	int capacity;//二叉堆的容量
	int m_num;//实际存放个数
	T *pHeap;
};

template<typename T>
void MaxHeap<T>::Insert(T data)
{
	if (m_num > capacity)
		return;
	pHeap[m_num] = data;
	
	InsertAmend(m_num);
	m_num++;
}

/*
1、找到当前需删除data的index
2、用最后的那个数值来代替index处的数值
3、调整成二叉堆的形式
*/
template<typename T>
void MaxHeap<T>::Delete(T data)
{
	int index = 0;
	
	while (index < m_num)
	{
		//找到则跳出循环
		if (data == pHeap[index])
			break;
		index++;
	}
	//未找到则返回
	if (index == m_num)
	{
		std::cout << "No find" << std::endl;
		return;
	}
	pHeap[index] = pHeap[--m_num];


	DeleteAmend(index);
	//删除最后的节点

}

/*调整思路:因为用最后的插入的孩子进行的替换,所以需要向下调整,
与孩子节点比较,小于孩子节点则进行交换数值
1、与孩子节点中最大的那个进行比较,孩子节点大则将孩子节点的值付给当前index
2、一直比较到最后
3、将index处的数值val付给最后找到的位置
*/
template<typename T>
void MaxHeap<T>::DeleteAmend(int index)
{
	int val = pHeap[index];

	int iChild = 2 * index + 1;//左孩子
	while (iChild < m_num)
	{
		if (pHeap[iChild] < pHeap[iChild + 1])
			iChild++;//变为右孩子的index
		if (pHeap[iChild] < pHeap[index])
		{
			break;
		}
		//调整
		pHeap[index] = pHeap[iChild];
		index = iChild;
		iChild = 2 * index + 1;
	}
	pHeap[index] = val;
}

template<typename T>
void MaxHeap<T>::Print()
{
	for (int i = 0; i < m_num; i++)
		std::cout << pHeap[i] << " ";
	std::cout << std::endl;
}

/*
调整的思路:向上与父节点比较、调整
1、插入的数值是插在数组的后面的
2、该数值与其父节点的数值比较,比父节点大的话则将父节点值付给该index
3、一直比较到根节点,直到找到小于父节点的index
4、将val付给该index
*/

template<typename T>
void MaxHeap<T>::InsertAmend(int index)
{
	T data = pHeap[index];
	while (index > 0)
	{
		int iParentIndex = (index - 1) / 2;
		//满足大顶堆,跳出循环
		if (pHeap[iParentIndex] > data)
		{
			break;
		}
		//不满足,父节点的值付给当前index,index变为父节点的
		else
		{
			pHeap[index] = pHeap[iParentIndex];
			index = iParentIndex;
		}
	}
	pHeap[index] = data;//data付给最新的索引处
}


//main.cpp
#include "MaxHeap.h"

int main()
{
	MaxHeap<int> heap(6);

	for (int i = 0; i < 6; i++)
	{
		heap.Insert(i);
	}
	heap.Print();

	heap.Delete(5);
	heap.Print();
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值