-
题目描述:
-
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
-
输入:
-
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
-
输出:
-
输出权值。
-
样例输入:
-
5 1 2 2 5 9
-
样例输出:
-
37
-
本人的方法是根据哈弗曼编码做的,第二种方法是使用优先队列做的,相对简单。
-
#include<stdio.h> #define MAX_N 1000 #define MAX_BIT 50 #define MAX_WEIGHT 100000 struct HuffNode //节点 { int parent; //父节点 int leftChild; //左孩子 int rightChild; //右孩子 int weight; //权值 }; struct HuffCode //叶节点编码 { char code[MAX_BIT]; int start; //编码的起始位置 int weight; }; //生成哈弗曼树 void huffmanTree(int weight[], int n, HuffNode huffTree[]) { int i,j; //一共有2n-1个节点,前n个叶节点,后n-1个非叶节点 for(i=0;i<2*n-1;i++) //节点初始化 { if(i<n) huffTree[i].weight=weight[i]; else huffTree[i].weight=0; huffTree[i].parent=-1; huffTree[i].leftChild=-1; huffTree[i].rightChild=-1; } //构造n-1个非叶节点 for(i=0;i<n-1;i++) { int m1=MAX_WEIGHT, m2=MAX_WEIGHT, x1=0,x2=0; for(j=0;j<n+i;j++)//找到权值最小的两个节点 { if(huffTree[j].parent==-1 && huffTree[j].weight<m1) { m2=m1; x2=x1; m1=huffTree[j].weight; x1=j; } else if(huffTree[j].parent==-1 && huffTree[j].weight<m2) { m2=huffTree[j].weight; x2=j; } } huffTree[n+i].weight=m1+m2; huffTree[n+i].leftChild=x1; huffTree[n+i].rightChild=x2; huffTree[x1].parent=n+i; huffTree[x2].parent=n+i; } } void huffmanCode(int n, HuffNode huffTree[],HuffCode huffCodes[]) { int i,j; for(i=0;i<n;i++) //n个叶节点 { int child=i; int parent=huffTree[child].parent; char c; int start=MAX_BIT-1; while(parent!=-1) { if(huffTree[parent].leftChild==child) c='0'; else c='1'; huffCodes[i].code[start]=c; start--; child=parent; parent=huffTree[child].parent; } huffCodes[i].start=start+1; huffCodes[i].weight=huffTree[i].weight; } } int main() { int n; while(scanf("%d",&n)!=EOF) { int i,sum=0; int weight[MAX_N]; HuffNode huffTree[2*MAX_N-1]; HuffCode huffCodes[MAX_N]; for(i=0;i<n;i++) scanf("%d",&weight[i]); huffmanTree(weight,n,huffTree); huffmanCode(n,huffTree,huffCodes); for(i=0;i<n;i++) sum=sum+huffCodes[i].weight*(MAX_BIT-huffCodes[i].start); printf("%d\n",sum); } }
#include<queue> #include<stdio.h> #include<vector> using namespace std; int main() { int n, i ; int temp; while(scanf("%d",&n)!=EOF) { priority_queue <int,vector<int>,greater<int> >q; //建立一个最小堆 int ans=0; for(i=0;i<n;i++) { scanf("%d",&temp); q.push(temp); } while(!q.empty() &&q.size()>1) { int a=q.top(); q.pop(); int b=q.top(); q.pop(); ans+=a+b; q.push(a+b); } printf("%d\n",ans); } return 0; }