POJ 3253 Fence Repair 哈夫曼树 优先队列
哈夫曼树的基本概念
转自:chengyaogen.blog.chinaunix.net
哈夫曼树(Huffman Tree),又叫最优二叉树,指的是对于一组具有确定权值的叶子结点的具有最小带权路径长度的二叉树。
(1)路劲(Path):从树中的一个结点到另一个结点之间的分支构成两个结点间的路径。
(2)路径长度(Path Length):路径上的分支树。
(3)树的路径长度(Path Length of Tree):从树的根结点到每个结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径长度最短。
(4)结点的权(Weight of Node):在一些应用中,赋予树中结点的一个有实际意义的树。
(5)结点的带权路径长度(Weight Path Length of Node):从该结点到树的根结点的路径长度与该结点的权的乘积。
(6)树的带权路径长度(WPL):树中所有叶子结点的带权路径长度之和,记为
![](http://blog.chinaunix.net/attachment/201204/1/26833883_1333284213e48q.jpeg)
在下图所示的四棵二叉树,都有4个叶子结点,其权值分别1、2、3、4,他们的带权路径长度分别为:
(a)WPL = 1 x 2 + 2 x 2 + 3 x 2 + 4 X 2 = 20
(b)WPL = 1 x 1 + 2 x 2 + 3 x 3 + 4 x 3 = 28
(c)WPL = 1 x 3 + 2 x 3 + 3 x 2 + 4 x 1 = 19
(d)WPL = 2 x 1 + 1 x 2 + 3 x 3 + 4 x 3 = 29
其中,(c)图所示的二叉树的带权路径长度最小,这棵树就是哈夫曼树。可以验证,哈夫曼树的带权路径长度最小。
哈夫曼树的构造算法
假设有n个权值,则构造出得哈夫曼树有n个叶子结点。n个权值分别设为w1,w2,...,wn,则哈夫曼树的构造规则为:
(1)将w1,w2,...,wn看成是有n棵树的森林(每棵树仅有一个结点);
(2)在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <queue> #include <stack> #include <vector> #include <deque> #include <set> #include <map> priority_queue<int, vector<int>, greater<int> > q; int main() { __int64 a,ans,sum=0; int n ; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++) { scanf("%I64d",&a); q.push(a); sum+=a; } ans=0; while(!q.empty()){ __int64 x=q.top(); q.pop(); __int64 y=q.top(); q.pop(); ans+=x+y; q.push(x+y); if(q.size()==1) break; } printf("%I64d\n",ans); } return 0; }
struct cmp1 { bool operator ()(int &a,int &b) { return a>b;//最小值优先 } }; struct cmp2 { bool operator ()(int &a,int &b) { return a<b;//最大值优先 } }; struct node1 { int u; bool operator < (const node1 &a) const { return u>a.u;//最小值优先 } }; struct node2 { int u; bool operator < (const node2 &a) const { return u<a.u;//最大值优先 } }; priority_queue<int>q1;//采用默认优先级构造队列 priority_queue<int,vector<int>,cmp1>q2;//最小值优先 priority_queue<int,vector<int>,cmp2>q3;//最大值优先 priority_queue<int,vector<int>,greater<int> >q4;//注意“>>”会被认为错误, //这是右移运算符,所以这里用空格号隔开,最小值优先 priority_queue<int,vector<int>,less<int> >q5;//最大值优先 priority_queue<node1>q6; //自定义优先级 priority_queue<node2>q7;