《算法笔记》9.8小节——图算法专题->哈夫曼树 问题 C: 哈夫曼树
题目描述
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出
输出权值。
样例输入
2
2 8
3
5 11 30
样例输出
10
62
分析:先建立哈夫曼树,然后求出每个节点的深度,再与权值相乘,最后求出所有节点的带权路径长度的之和输出。代码可以参考问题B。
#include<algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#define INF 0xffffffff
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<endl
#define db5(x,y,z,r,w) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<", "<<#w<<"="<<(w)<<endl
using namespace std;
typedef struct node
{
int val,index;
struct node *lchild,*rchild,*father;
}node;
struct CompareNodePtr
{
bool operator()(const node *a, const node *b)const
{
if(a->val==b->val)return a->index>b->index; // val 相同,则 index 小的优先
return a->val>b->val; // val 小的优先
}
};
void dfs(int ss[],node *root,int temp,int n)
{
if(root==NULL)return;
// db2(root->val,root->index);
if(root->index<=n&&root->index>=1)
{
// db1(root->val);
ss[root->index]=temp*root->val;return;
}
dfs(ss,root->lchild,temp+1,n);
dfs(ss,root->rchild,temp+1,n);
}
void Free(node *root)
{
if(root==NULL)return;
Free(root->lchild);
Free(root->rchild);
free(root);
return;
}
int main(void)
{
#ifdef test
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
clock_t start=clock();
#endif //test
int n;
while(~scanf("%d",&n))
{
vector<node*>num(n+5);
priority_queue<node*,vector<node*>,CompareNodePtr>q;
for(int i=0;i<n;++i)
{
num[i]=(node*)malloc(sizeof(node));
num[i]->lchild=num[i]->rchild=num[i]->father=NULL;
num[i]->index=i+1; // 赋值索引
scanf("%d",&num[i]->val);
q.push(num[i]);
}
int mergeIndex=n+1;
node *x,*y;
while(q.size()>1)
{
x=q.top(),q.pop();
y=q.top(),q.pop();
// 确保 x->index < y->index 以符合 `seletMin` 逻辑
if(x->index>y->index)swap(x,y);
node *temp=(node*)malloc(sizeof(node));
temp->val=x->val+y->val;
temp->lchild=x,temp->rchild=y;
x->father=y->father=temp;
temp->index=mergeIndex++; // 赋予新的索引值
q.push(temp);
}
node *root=q.top();q.pop();
int ss[n+5]={0};
dfs(ss,root,0,n);
int ans=0;
for(int i=1;i<=n;++i)
ans+=ss[i];
printf("%d\n",ans);
Free(root);
}
#ifdef test
clockid_t end=clock();
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\n\n\n\n");
cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位
cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位
#endif //test
return 0;
}