二叉堆数据结构是一个数组对象,可以将它看做一个二叉树;如下图所示。
树的根是A[1],对应节点下标k,其父亲、左孩子、右孩子下标可以直接计算得到
--------------------------------------------------------------------------------------------------------
Parent(k)
return [k/2] 向下取整
Left(k)
return 2k
Right(k)
return 2k+1
------------------------------------------------------------------------------------------------------
有两种堆,最大堆和最小堆,对于最大堆
A[Parent(k)]>=A[k]
二叉堆的创建和维护
维护
A[i]的左右两个孩子都已经构成堆,但是A[i]可能不符合堆的要求(最大堆或最小堆)
假设要维护的是最大堆,此时比较A[i]与左右两个孩子,如果A[i]不是最大的,则与其较大的一个孩子交换,再去递归的维护这个孩子即可。
添加元素:把元素加到末尾,之后维护其父节点,递归的维护父节点。这是一个“向上冒”的过程。
删除元素:删除某一位置元素,把最后一个元素放到这个位置,维护这个位置的元素。
创建
创建堆的过程其实就是自底往上维护堆的过程。因为A[n/2+1,n/2+2,....,n]都是叶子节点,因此只需依次维护A[n/2],A[n/2-a],...,A[1]即可创建堆
实例如下:
main.cpp
#include <iostream>
#include <vector>
#include "heap.h"
using namespace std;
int main()
{
vector<int> test;
int k;
for (int i=0;i<10;i++)
{
cin>>k;
test.push_back(k);
}
for (int i=Parent(test.size()-1);i>=0;i--)
{
heapify(test,i);
}
for(vector<int>::iterator it=test.begin();it!=test.end();it++)
{
cout<<*it<<' ';
}
return 0;
}
heap.h
#ifndef HEAP_H
#define HEAP_H
using std::vector;
int Left(int k)//找左孩子
{
return 2*k+1;
}
int Right(int k)
{
//找右孩子
return 2*(k+1);
}
int Parent(int k)
{
//找父节点
return (k-1)/2;
}
void heapify(vector<int> &v,int k)
{
//维护堆的节点K,假设堆是最大堆
int l=Left(k),r=Right(k),most=k;//most存放最大元素
if (l<v.size()&&v[l]>v[k])//左边节点大于要维护的节点
{
most=l;
}
if (r<v.size()&&v[r]>v[most])//右边节点最大
{
most=r;
}
if (most!=k)
{
//交换元素
int tmp=v[k];
v[k]=v[most];
v[most]=tmp;
//递归维护
heapify(v,most);
}
}
#endif