- 二叉堆
定义:二叉堆是完全二叉树或近似完全二叉树。
二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,
且每个节点的左子树和右子树都是一个二叉堆。
它分为两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
最大堆示意图,数组中的存储形式在下面
- 插入
插入的数值先放在堆的最后,然后与其父节点进行比较交换
- 删除
用最后的数值来替换需要删除的数值,然后与其子节点中最大的值比较交换
//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;
}