【问题描述】
现在有N堆果子,要把他们合并为一堆。每次合并只能合并其中的两堆,假如要合并的两堆果子分别有a颗果子和b颗果子,那么合并这两堆果子需要消耗a+b点体力。问合并完所有果子需要最小的体力数是多少。
【输入形式】
共两行。
第一行为一个正整数N<=1000。表示果子总共有多少堆。
第二行共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 {
public:
priorityQueue(int capacity = 100);
priorityQueue(const T data[], int size);
~priorityQueue();
bool isEmpty() const;
void enQueue(const T & x);
T deQueue();
T getHead() const;
int size() const { return currentSize; }
int findMin(T x) { // 找出大于等于x的最小元素
T Min;
int ID = -1;
for(int i = 1; i <= currentSize; ++i)
if (array[i] >= x && (Min == -1 || array[i] < Min)) {
Min = array[i];
ID = i;
}
return ID;
}
void decreaseKey(int i, T value) { // 将堆中第i个结点的值减少value
T x;
int hole;
array[hole = i] -= value; // 将第i个元素减少value
for(x = array[i]; hole>1 && x < array[hole/2]; hole /= 2)//过滤
array[hole] = array[hole / 2];
array[hole] = x;
}
private:
int currentSize;
T *array;
int maxSize;
void doubleSpace() ;
void buildHeap() ;
void percolateDown(int hole); //向下过滤
};
template < class T>
priorityQueue<T>::priorityQueue(int capacity)
{
array = new T[capacity];
maxSize = capacity;
currentSize = 0;
}
template < class T>
priorityQueue<T>::priorityQueue(const T* items, int size) :maxSize(size + 10), currentSize(size)
{
array = new T[maxSize];
for (int i = 0; i <= currentSize; ++i)
array[i] = items[i];
buildHeap();
}
template < class T>
priorityQueue<T>::~priorityQueue()
{
delete[]array;
}
template < class T>
bool priorityQueue<T>::isEmpty()const
{
return currentSize == 0;
}
template < class T>
T priorityQueue<T>::getHead()const
{
return array[1];
}
template < class T>
void priorityQueue<T>::enQueue(const T& x)
{
if (currentSize == maxSize - 1) doubleSpace();
int hole = ++currentSize;
for (; hole > 1 && x < array[hole / 2]; hole /= 2)
array[hole] = array[hole / 2];
array[hole] = x;
}
template < class T>
void priorityQueue<T>::doubleSpace()
{
T* tmp = array;
maxSize *= 2;
array = new T[maxSize];
for (int i = 0; i <= currentSize; ++i)
array[i] = tmp[i];
delete[]tmp;
}
template < class T>
T priorityQueue<T>::deQueue()
{
T minItem;
minItem = array[1];
array[1] = array[currentSize--];
percolateDown(1);
return minItem;
}
template < class T>
void priorityQueue<T>::percolateDown(int hole)
{
int child;
T tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child)
{
child = hole * 2;
if (child != currentSize && 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>::buildHeap()
{
for (int i = currentSize / 2; i > 0; i--)
percolateDown(i);
}
cpp文件:
#include <iostream>
#include "priorityQueue.h"
using namespace std;
int main()
{
int n, num;
priorityQueue<int> q;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> num;
q.enQueue(num);
}
int ans = 0, a, b;
while (q.size() > 1)
{
a = q.deQueue();
b = q.deQueue();
ans += a + b;
q.enQueue(a + b);
}
cout << ans << endl;
return 0;
}
吐槽:本道题是作业题,课程进度还没到优先级队列,所以老师期待的做法应该不是用优先级队列实现哈夫曼;但是……我不会其他的,如果有其他优秀做法欢迎留言!!