一、题目
给定n个权值作为n个叶子结点,构造哈夫曼树, 求其带权路径长度。
二、分析
带权路径长度得计算方法有两种:第一是定义法,第二是等于各个非叶子结点的权值之和。
这里我们用方法二计算,但是按照老方法,先构造一个哈夫曼树,之后再来计算会超时,所以这里我们不构造。可是对每次结果进行排序得话,再来选取最小得两个权值,函数会超时。所以我有点无能为力。然后在百度上搜索了一下,发现很多人都是使用优先队列做出来来的。所以我查阅了一下关于优先队列得知识。如下:
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
优先队列的时间复杂度为O(logn),n为队列中元素的个数,其存取都需要时间。
在默认的优先队列中,优先级最高的先出队。默认的int类型的优先队列中先出队的为队列中较大的数。
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
一般是:
//升序队列,小顶堆 priority_queue <int,vector,greater > q;
//降序队列,大顶堆priority_queue <int,vector,less >q;
数据结构:优先队列,小顶堆。
优先访问小者。
三、算法实现
(主要代码)
typedef unsigned long Lu;
int main()
{
int n,i;
Lu sum,a,b,y,x;
while(scanf("%d",&n)==1)
{
sum=0;
priority_queue <Lu,vector<Lu>,greater<Lu> > q;//小丁堆得使用
while(!q.empty())
q.pop();
for(i=1;i<=n;i++)
{
cin>>x;
q.push(x);
}
for(i=2;i<=n;i++)
{
a=q.top();
q.pop();
b=q.top();
q.pop();
y=a+b;
sum=(sum+y)%1000000007;//计算带权路径长度
q.push(y);
}
printf("%lu\n",sum%1000000007);
}
return 0;
}
四、算法分析
算法分析:优先队列的时间复杂度为O(logn),n为队列中元素的个数,其存取都需要时间。计算过程为O(N)。故其时间复杂度为O(N)。
空间复杂度:O(N).