堆果子的优先级队列优化
【问题描述】
现在有N堆果子,要把他们合并为一堆。每次合并只能合并其中的两堆,假如要合并的两堆果子分别有a颗果子和b颗果子,那么合并这两堆果子需要消耗a+b点体力。问合并完所有果子需要最小的体力数是多少。
【输入形式】
共两行。
第一行为一个正整数N<=500000。表示果子总共有多少堆。
第二行共N个正整数,ai表示第i堆果子的数目。
【输出形式】
一个正整数,表示消耗的最小体力数。
【样例输入】
5
1 2 3 4 5
【样例输出】
33
【样例说明】
合并1,2消耗体力3,产生一个大小为3的果子堆。
合并4,5消耗体力9,产生一个大小为9的果子堆。
合并3,3消耗体力6,产生一个大小为6的果子堆。
合并6,9消耗体力15,产生一个大小为15的果子堆。
共消耗体力33.
#pragma once
template<class T>
class priorityQueue//class 是类的标志勿忘
{
private:
int currentLength;
int maxSize;
T*array;
void doubleSpace();
void percolateDown(int hole);//向下过滤
public:
void buildHeap();//建堆
priorityQueue(const T*items, int size);
priorityQueue(int size = 100)
{
maxSize = size;
currentLength = 0;
array = new T[size];
}
~priorityQueue() { delete[]array; }//构造析构类
bool isEmpty()const { return currentLength == 0; }//询问类
T getHead() { return array[1]; }
void enQueue(const T&x);//非常量引用的初始值必须为左值
T deQueue();//一般出队都会返回出队值以保存
int size() { return currentLength; }
};
template < class T>
void priorityQueue<T>::enQueue(const T& x)
{
if (currentLength == maxSize - 1) doubleSpace();
int hole = ++currentLength;
for (; hole > 1 && x < array[hole / 2]; hole /= 2)
array[hole] = array[hole / 2];
array[hole] = x;
}
template<class T>
T priorityQueue<T>::deQueue()
{
T tmp = array[1];
array[1] = array[currentLength--];//提上来开始落,cl从1开始
percolateDown(1);//模块化
return tmp;
}
template<class T>
void priorityQueue<T>::percolateDown(int hole) {
int child;
T tmp = array[hole];
for (; hole * 2 <= currentLength; hole = child)
{
child = hole * 2;
if (child != currentLength && array[child + 1] < array[child])
child++;
if (array[child] < tmp) {
array[hole] = array[child];
}
else break;
}
array[hole] = tmp;
}
template<class T>
void priorityQueue<T>::doubleSpace()
{
int i;//留个tmp保存原数据,array扩大
T*tmp = array;
array = new T[2 * maxSize];
for (i = 0; i < maxSize; i++)
{
array[i] = tmp[i];
}
maxSize *= 2;//成员函数操作对其他变量的影响
delete tmp;//工具人就是用来delete掉的
}
template<class T>
void priorityQueue<T>::buildHeap()//建堆
{
int i;
for (i = currentLength / 2; i >= 1; i--)
{
percolateDown(i);//前提是已经构造好
}
}
template<class T>//带参数的构造函数
priorityQueue<T>::priorityQueue(const T*items, int size)
{
maxSize = size + 10;
currentLength = size;
int i;
array = new T[maxSize];//此时只是定义了array,尚未赋值,是maxSize
for (i = 1; i <= currentLength; i++)
{
array[i] = items[i - 1];
}
buildHeap();
}
#include<iostream>
using namespace std;
int main()
{
int n, i, tmp1, tmp2;
long long int sum=0;
cin >> n;
priorityQueue<int>x;
int*t = new int[n];
for (i = 0; i <= n - 1; i++)
{
cin >> t[i];
x.enQueue(t[i]);
}
while (x.size()>1)
{
tmp1 = x.deQueue();
tmp2 = x.deQueue();
x.enQueue(tmp1 + tmp2);
sum = sum + tmp1 + tmp2;
}
cout << sum << '\n';
system("pause");
delete[]t;
}