以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 算法理论与分析 』  (http://bbs.xml.org.cn/list.asp?boardid=60)
----  [求助]哈夫曼树的构造  (http://bbs.xml.org.cn/dispbbs.asp?boardid=60&rootid=&id=56927)


--  作者:sjbird331
--  发布时间:12/19/2007 9:25:00 AM

--  [求助]哈夫曼树的构造
近几天做了一些哈夫曼树的问题,发现有的参考书中对于哈夫曼树的构造问题存在不同的理解,这种理解造成了我在做题时的困惑。现在就把这些困惑的地方写出来,希望有兴趣的朋友能给我解答,谢谢
(1)有的参考书上说,从给定序列T中选取权值最小的和次小的作为合并之后树的左、右孩子;而还有一些参考书则直接没有这种规定,直接选取较小的两个结点,而对于谁为左、右孩子,则没有规定。请问在实际的哈夫曼树构造过程中,我们应该遵循一个什么样的原则进行合并呢?
(2)我做的一些题中,总是存在这样一个问题:构造完成后的哈夫曼树的带权路径长度总是正确的,但是构造之后树的结构和答案给出的哈夫曼树的结构存在一些差异,这种差异体现在原序列中结点的次序不对,比如说,答案中结点3和结点4分别为合并之后树的左、右孩子,但是我做出来的却是结点4和结点3分别为左、右孩子。请问,这种差异是正常的还是不正常的,WPL一样,但是结点的相对次序不一样(当然,对应的结点总是在同一层)
请大家帮我想想这是怎么回事,谢谢
--  作者:weiyild
--  发布时间:12/23/2007 9:59:00 PM

--  
做树的时候加入一条让小的固定做左孩子或者右孩子,然后做出的树应该就有序了
--  作者:zlsbm
--  发布时间:12/24/2007 10:50:00 AM

--  
首先得知道,哈夫曼树并不是唯一的,但在构造时需要确定条让小的固定做左孩子或者右孩子,那么如果没有权值相同的点,则应当是唯一的。
--  作者:sjbird331
--  发布时间:12/24/2007 7:36:00 PM

--  
在实际的做题过程中,题目通常对谁做左孩子,谁做右孩子没有限定,所以解题过程中是不是由我们自己进行约定
--  作者:weiyild
--  发布时间:12/24/2007 8:02:00 PM

--  
其实我觉得哈夫曼树的本质是让wpl值最低,所以我觉得左右子树颠倒不影响这个树的设计要求,如果希望让权值按某个顺序进行排序的话只要设定下就好了哦,相等的话可以根据其序列进行选择,这样的话就不会引起做出的树不确定了吧!
--  作者:冬天的农夫
--  发布时间:2/2/2008 7:58:00 PM

--  
一般来说,在霍夫曼树中,得最小权值的节点是由最小堆取得的。每次从最小堆中取得两个节点。左右顺序只要规定好,就不会有错误。
--  作者:LCW123
--  发布时间:5/22/2008 12:27:00 PM

--  
哈夫曼树不唯一 ,不管怎样,带权路径长度总是最小且为固定之,产生的编码值是唯一的
可以从给定序列T中选取权值最小的和次小的作为合并之后树的左、右孩子入手,实现如下:
typedef struct HaffNode
{
 int weight;
 int parent;
 int lchild;
 int rchild;
}HaffNode;
void HaffMan(int w[],int n,HaffNode HNode[])
{
 int min1, min2;
 int l_index, r_index; // 最小和次小权值的索引
 for(int i = 0; i <= 2*n-1; i++)
 {
  if(i <= n-1) HNode[i].weight = w[i];
  else HNode[i].weight = 0;
  HNode[i].parent = -1;
  HNode[i].lchild = -1;
  HNode[i].rchild = -1;
 }
 for(i = 0; i < n-1; i++) // 0 ... n-2
 {
  for(int j = 0; ; j++)   //查找未构造的哈夫曼节点
   if(HNode[j].parent == -1) break;
  min1 = min2 = HNode[j].weight;
  l_index = r_index = j;
  for(int k = j; k < n+i; k++) // j < n+n-2
  {
   if(HNode[k].weight < min1 && HNode[k].parent == -1)
   {
    min2 = min1;
    min1 = HNode[k].weight; // 最小权值
    r_index = l_index;
    l_index = k;
   }
   else if(((HNode[k].weight < min2 && HNode[k].weight > min1) || min1 == min2) && HNode[k].parent == -1)
   {
    min2 = HNode[k].weight; // 次最小权值
    r_index = k;
   }
  }
  HNode[l_index].parent = n + i;
  HNode[r_index].parent = n + i;
  HNode[n+i].weight = min1 + min2;
  HNode[n+i].lchild = l_index;
  HNode[n+i].rchild = r_index;
 }
}
int main(void)
{
 int w[] = {2,6,1,8,3,1,2};
 int n = sizeof(w) / sizeof(w[0]);
 HaffNode*  ht = new HaffNode[2*n-1];
 HaffMan(w,n,ht);
 for(int i = 0; i < 2*n-1; i++)
 {
  cout<<"num = "<<i<<", weight = "<<ht[i].weight
   <<", parent = "<<ht[i].parent<<", lchild = "
   <<ht[i].lchild<<", rchild = "<<ht[i].rchild<<endl;
 }
 return 0;
}

W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
1,519.531ms