hzCPPOJ

哈夫曼树(最优二叉树)

时间限制:  1 s      内存限制:   128 MB
提交:19     正确:4     分值:99

题目描述

(1) 以权值分别为W1,W2...Wn的n各结点,构成n棵二叉树T1,T2,...Tn并组成森林F={T1,T2,...Tn},其中每棵二叉树 Ti仅有一个权值为 Wi的根结点;

(2) 在F中选取两棵根结点权值最小的树作为左右子树构造一棵新二叉树,并且置新二叉树根结点权值为左右子树上根结点的权值之和(根结点的权值=左右孩子权值之和,叶结点的权值= Wi);

(3) 从F中删除这两棵二叉树,同时将新二叉树加入到F中;

(4) 重复(2)、(3)直到F中只含一棵二叉树为止,这棵二叉树就是Huffman树。


考虑到对于有n个叶子结点的哈夫曼树有2n-1个结点,并且进行n-1次合并操作,为了便于选取根节点权值最小的二叉树以及合并操作,设置一个数组haftree[2n-1],保存哈夫曼树中的各个结点的信息,数组元素的结点结构如下图所示:

weight lchild rchild parent


哈夫曼树的结点结构

其中,weight保存结点权值;

lchild保存该节点的左孩子在数组中的下标;

rchild保存该节点的右孩子在数组中的下标;

parent保存该节点的双亲孩子在数组中的下标。

可以用C++语言中的结构体类型定义上述结点,如下:


 // 哈夫曼树的结点结构 
 struct element  { 
 int weight; // 权值域
 int lchild, rchild, parent; // 该结点的左、右、双亲结点在数组中的下标 
 };



输入

输入两行数据

第一行 为需要输入的 权重的个数,整数 n

第二行为 n个权重,用空格分开数据。

输出

第一行输出i字符串“ndex weight parent lChild rChild”

第二行起输出2*n-1行,赫夫曼树的各个结点数据,与第一行字符串对应字段输出,每个字段控制字符宽度为6

样例

样例输入:
8 5 29 7 8 14 23 3 11
样例输出:
index weight parent lChild rChild 0 5 8 -1 -1 1 29 13 -1 -1 2 7 9 -1 -1 3 8 9 -1 -1 4 14 11 -1 -1 5 23 12 -1 -1 6 3 8 -1 -1 7 11 10 -1 -1 8 8 10 6 0 9 15 11 2 3 10 19 12 8 7 11 29 13 4 9 12 42 14 10 5 13 58 14 1 11 14 100 -1 12 13
样例输入:
5 3 7 8 6 21
样例输出:
index weight parent lChild rChild 0 3 5 -1 -1 1 7 6 -1 -1 2 8 6 -1 -1 3 6 5 -1 -1 4 21 8 -1 -1 5 9 7 0 3 6 15 7 1 2 7 24 8 5 6 8 45 -1 4 7

提示

为了判定一个结点是否已经加入哈夫曼树中,可通过parent域的值来确定。初始时parent的值为-1,当某结点加入到树中时,该节点parent域的值为其双亲结点在数组中的下标。

构造哈夫曼树时,首先将n个权值的叶子结点存放到数组haftree的前n个分量中,然后不断将两棵子树合并为一棵子树,并将新子树的根节点顺序存放到数组haftree的前n个分量的后面。

哈夫曼算法用伪代码描述为:


1、数组haftree初始化,所有数组元素的双亲、左右孩子都置为-1;
2、数组haftree的前n个元素的权值置给定权值;
3、进行n-1次合并
    3.1 在二叉树集合中选取两个权值最小的根节点,其下标分别为i1,i2;
    3.2 将二叉树i1、i2合并为一棵新的二叉树k。


提交人

bpxiao

来源/分类