最小堆,是完全二叉树,其基本定义是任何一个节点小于其左右子树的节点
常见操作:加入一个值,取最小值,删除最小值
加入一个值,直接加入到末尾a[size++] 然后该元素上浮到合适位置
最大值即根节点 a[0]
删除最小值,让末尾元素填充到a[0] 然后该元素下沉到合适位置
下沉过程中,选取左右子节点的最小值,上浮(任满足节点大于左右子树)
易错点,树中没有节点,以及下沉过程中,是否存在左右子树的判断(即基本的数组区间判断)
class heap
{
public:
int arr[1000];
int size=0;
void push(int data) //新来元素填充到末尾 然后上浮到合适位置
{
arr[size] = data;
up(size);
size++;
}
void up(int index) //arr[index]位置元素上浮
{
if (index == 0)
return;
int flag = arr[index];
while (((index - 1) / 2) >= 0 && arr[(index - 1) / 2] > flag)
{
arr[index] = arr[(index - 1) / 2];
index = (index - 1) / 2;
if (index == 0)
break;
}
arr[index] = flag;//最终填入位置
}
int min()
{
return arr[0];
}
void del() //删除根元素 最小元素后 最后元素填上,然后下沉
{
if(size == 0 || size == 1)
{
size = 0;
return;
}
arr[0] = arr[size - 1];//将最后一个填充到根顶部
size--;
down(0);//从根节点开始下沉
}
void down(int index) //arr[index]位置元素下沉
{
if (index * 2 + 1 >= size) //已经到叶子节点了
return;
else
{
if (index * 2 + 2 < size) //还存在右子树
{
if (arr[index * 2 + 1] < arr[index * 2 + 2])
{
if (arr[index * 2 + 1] > arr[index])
return;
else
{
int tmp = arr[index];
arr[index] = arr[index * 2 + 1];
arr[index * 2 + 1] = tmp;
down(index * 2 + 1);
}
}
else
{
if (arr[index * 2 + 2] > arr[index])
return;
else
{
int tmp = arr[index];
arr[index] = arr[index * 2 + 2];
arr[index * 2 + 2] = tmp;
down(index * 2 + 2);
}
}
}
else //不存在右子树
{
if (arr[index * 2 + 1] > arr[index])
return;
else
{
int tmp = arr[index];
arr[index] = arr[index * 2 + 1];
arr[index * 2 + 1] = tmp;
// down(index * 2 + 1);
}
}
}
}
};