二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。
二叉堆有两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。
#include
#include
#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )
static int m_heap[30]; // 数据
static int m_capacity=30; // 总的容量
static int m_size=0; // 实际容量(初始化为0)
/*
* 返回data在二叉堆中的索引
*
* 返回值:
* 存在 -- 返回data在数组中的索引
* 不存在 -- -1
*/
int get_index(int data)
{
int i=0;
for(i=0; i= m_heap[l])
break; //调整结束
else
{
m_heap[c] = m_heap[l];
c = l;
l = 2*l + 1;
}
}
m_heap[c] = tmp;
}
/*
* 删除最大堆中的data
*
* 返回值:
* 0,成功
* -1,失败
*/
int maxheap_remove(int data)
{
int index;
// 如果"堆"已空,则返回-1
if(m_size == 0)
return -1;
// 获取data在数组中的索引
index = get_index(data);
if (index==-1)
return -1;
m_heap[index] = m_heap[--m_size]; // 用最后元素填补
maxheap_filterdown(index, m_size-1); // 从index位置开始自上向下调整为最大堆
return 0;
}
/*
* 最大堆的向上调整算法(从start开始向上直到0,调整堆)
*
* 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
*
* 参数说明:
* start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
*/
static void maxheap_filterup(int start)
{
int c = start; // 当前节点(current)的位置
int p = (c-1)/2; // 父(parent)结点的位置
int tmp = m_heap[c]; // 当前节点(current)的大小
while(c > 0)
{
if(m_heap[p] >= tmp)
break;
else
{
m_heap[c] = m_heap[p];
c = p;
p = (p-1)/2;
}
}
m_heap[c] = tmp;
}
/*
* 将data插入到二叉堆中
*
* 返回值:
* 0,表示成功
* -1,表示失败
*/
int maxheap_insert(int data)
{
// 如果"堆"已满,则返回
if(m_size == m_capacity)
return -1;
m_heap[m_size] = data; // 将"数组"插在表尾
maxheap_filterup(m_size); // 向上调整堆
m_size++; // 堆的实际容量+1
return 0;
}
/*
* 打印二叉堆
*
* 返回值:
* 0,表示成功
* -1,表示失败
*/
void maxheap_print()
{
int i;
for (i=0; i
#include
#include
#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )
static int m_heap[30];
static int m_capacity=30; // 总的容量
static int m_size=0; // 实际容量(初始化为0)
/*
* 返回data在二叉堆中的索引
*
* 返回值:
* 存在 -- 返回data在数组中的索引
* 不存在 -- -1
*/
int get_index(int data)
{
int i=0;
for(i=0; i m_heap[l+1])
l++; // 左右两孩子中选择较小者,即m_heap[l+1]
if(tmp <= m_heap[l])
break; //调整结束
else
{
m_heap[c] = m_heap[l];
c = l;
l = 2*l + 1;
}
}
m_heap[c] = tmp;
}
/*
* 删除最小堆中的data
*
* 返回值:
* 0,成功
* -1,失败
*/
int minheap_remove(int data)
{
int index;
// 如果"堆"已空,则返回-1
if(m_size == 0)
return -1;
// 获取data在数组中的索引
index = get_index(data);
if (index==-1)
return -1;
m_heap[index] = m_heap[--m_size]; // 用最后元素填补
minheap_filterdown(index, m_size-1); // 从index号位置开始自上向下调整为最小堆
return 0;
}
/*
* 最小堆的向上调整算法(从start开始向上直到0,调整堆)
*
* 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
*
* 参数说明:
* start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
*/
static void filter_up(int start)
{
int c = start; // 当前节点(current)的位置
int p = (c-1)/2; // 父(parent)结点的位置
int tmp = m_heap[c]; // 当前节点(current)的大小
while(c > 0)
{
if(m_heap[p] <= tmp)
break;
}
m_heap[c] = tmp;
}
/*
* 将data插入到二叉堆中
*
* 返回值:
* 0,表示成功
* -1,表示失败
*/
int minheap_insert(int data)
{
// 如果"堆"已满,则返回
if(m_size == m_capacity)
return -1;
m_heap[m_size] = data; // 将"数组"插在表尾
filter_up(m_size); // 向上调整堆
m_size++; // 堆的实际容量+1
return 0;
}
/*
* 打印二叉堆
*
* 返回值:
* 0,表示成功
* -1,表示失败
*/
void minheap_print()
{
int i;
for (i=0; i
借助C++STL种的vector 还有一些函数等
首先建立一个动态数组vector
然后可以根据自己的需求写一个比较,来实现大根堆或者小根堆
//实现大根堆
bool cmp(int a,int b)
{
return a < b;
}
//声明数组
vector v;
//插入元素
cin >> n;
v.push_back(n);
//建堆
make_heap(v.begin(),v.end(),cmp);
//取得堆顶元素,此时为最大元素或者最小元素
int t = v[0];
//此时并没有删除,需要我们手动来实现
//首先将堆顶元素置于最后,重新排堆
pop_heap(v.begin(),v.end(),cmp);
//然后弹出最后一个元素
v.pop_back();
//到此实现了一步完整的操作
利用优先队列 priority_queue
具体用法可以参考优先队列的用法
内部重载 < 来实现 大根堆或者小根堆
例题http://codevs.cn/problem/1063/
第二种堆写法AC代码:
#include
using namespace std;
const int N = 1e6 + 5;
bool cmp(int a,int b)
{
return a > b;
}
int main()
{
ios::sync_with_stdio(false);
vector v;
int n, t;
cin >> n;
for(int i = 1;i <= n;i ++)
{
cin >> t;
v.push_back(t);
}
make_heap(v.begin(),v.end(),cmp);
long long sum = 0;
while(v.size() > 1)
{
//先取得一个最小元素
t = v[0];
//弹出,维护 再取第二个
pop_heap(v.begin(),v.end(),cmp);
v.pop_back();
//维护堆,再取第二次
push_heap(v.begin(),v.end(),cmp);
t += v[0];
pop_heap(v.begin(),v.end(),cmp);
v.pop_back();
sum += t;
//重新加入元素 维护堆
v.push_back(t);
push_heap(v.begin(),v.end(),cmp);
}
cout << sum <
#include
using namespace std;
const int N = 1e6 + 5;
int main()
{
ios::sync_with_stdio(false);
priority_queue, greater > heap;
int n, t;
cin >> n;
for(int i = 1;i <= n;i ++)
{
cin >> t;
heap.push(t);
}
long long sum = 0;
while(heap.size() > 1)
{
int t1 = heap.top();
heap.pop();
int t2 = heap.top();
heap.pop();
sum += t1 + t2;
heap.push(t1 + t2);
}
cout << sum << endl;
return 0;
}