您的位置:首页 > 其它

堆(插入,删除)

2016-05-08 23:01 411 查看
首先呢,先来了解一个何为堆?
堆数据结构是一种数组对象,它可被视为一棵完全二叉树结构。
堆结构的二叉树存储是:
最大堆:每个父节点的都大于孩子节点
最小堆:每个父节点的都小于孩子节点


最大堆:a[] = {19,17,18,14,16,13,15,12,10,11}
最小堆:a[] = {10,11,13,12,16,18,15,17,14,19}

代码实现最大堆:
#pragma once
#include <iostream>
#include <assert.h>
#include <vector>

using namespace std;

template <class T>
class Heap
{
public:
Heap()   //无参构造函数
{}

Heap(T* a,size_t size)
{
for(size_t i=0;i<size;++i)
{
_a.push_back(a[i]);
}
//建堆
for(int i=(_a.size()-2)/2;i>=0;--i)
{
_ApDown(i);
}
}

void Push(const T& x)//插入元素
{
_a.push_back(x);//在堆尾插入元素
_ApHeapUp(_a.size()-1);	//向上调整
}

void Pop()//删除(删除优先级高)
{
swap(_a[0],_a[_a.size()-1]);//交换堆的第一个元素和最后一个元素
_a.pop_back();//删除最后一个元素
_ApDown(0);//向下调整
}

size_t Size()//堆的大小
{
return _a.size();
}

bool Empty()//堆是否为空
{
return _a.empty();
}

public:
void _ApDown(size_t parent)
{
size_t child = parent*2+1;

while(child < _a.size())
{
//找到左右孩子中较大的
if((child+1) < _a.size() && _a[child+1] > _a[child])
{
++child;
}
//比较较大孩子与父亲
if(_a[child] > _a[parent]) //(2)
{
swap(_a[child],_a[parent]);
parent = child;
child = parent*2+1;
}
else
{
break;
}
}
}

void _ApHeapUp(size_t child)
{
size_t parent = (child-1)/2;
while(child > 0)
{
if(_a[child] > _a[parent])//比较孩子与父亲 (3)
{
swap(_a[child],_a[parent]);
child = parent;
parent = (child-1)/2;
}
else
{
break;
}
}
}

protected:
vector<T> _a;
};


若要实现最小堆,可将上述代码中(1)(2)(3)处的大于改为小于即可。
但是这样使得代码冗余,不容易维护。
那么如何用一个来实现即可建最大堆也可建最小堆呢?我们之前见的仿函数就用上场喽!
回顾一下什么是仿函数?
仿函数的机制就是通过对()进行重载。

template <class T>
struct Less  //小于
{
bool operator()(const T& l,const T& r)
{
return l < r;
}
};

template <class T>
struct Greater  //大于
{
bool operator()(const T& l,const T& r)
{
return l > r;
}
};

template <class T,class Comper = Greater<T> >//默认建大堆
class Heap
{
public:
Heap()   //无参构造函数
{}

Heap(T* a,size_t size)
{
for(size_t i=0;i<size;++i)
{
_a.push_back(a[i]);
}
//建堆
for(int i=(_a.size()-2)/2;i>=0;--i)
{
_ApDown(i);
}
}

void Push(const T& x)//插入元素
{
_a.push_back(x);//在堆尾插入元素
_ApHeapUp(_a.size()-1);	//向上调整
}

void Pop()//删除(删除优先级高)
{
swap(_a[0],_a[_a.size()-1]);//交换堆的第一个元素和最后一个元素
_a.pop_back();//删除最后一个元素
_ApDown(0);//向下调整
}

size_t Size()//堆的大小
{
return _a.size();
}

bool Empty()//堆是否为空
{
return _a.empty();
}

public:
void _ApDown(size_t parent)
{
size_t child = parent*2+1;

while(child < _a.size())
{
Comper com;
//找到左右孩子中较大的
if((child+1) < _a.size() && com(_a[child+1],_a[child]))
{
++child;
}
//比较较大孩子与父亲
if(com(_a[child],_a[parent]))
{
swap(_a[child],_a[parent]);
parent = child;
child = parent*2+1;
}
else
{
break;
}
}
}

void _ApHeapUp(size_t child)
{
size_t parent = (child-1)/2;
Comper com;
while(child > 0)
{
if(com(_a[child],_a[parent]))//比较孩子与父亲
{
swap(_a[child],_a[parent]);
child = parent;
parent = (child-1)/2;
}
else
{
break;
}
}
}

protected:
vector<T> _a;
};
测试函数:
void Test1()
{
int a[] = {10,16,18,12,11,13,15,17,14,19};
//Heap<int> hp(a,sizeof(a)/sizeof(a[0]));  //默认建大堆
Heap<int,Less<int> > hp1(a,sizeof(a)/sizeof(a[0])); //建小堆
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: