带权路径长度

一、题目

给定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).

猜你喜欢

转载自blog.csdn.net/King0237/article/details/111195595