构造HuffmanTree

Huffman算法思想:

(1)根据给定的n个权值{w1,w2,...wn}构成n课二叉树的森林F={T1,T2,...,Tn},其中每课二叉树Ti中只有一个带权为wi的根结点,且其左右子树为空。

(2)在森林F中选取两课根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左,右子树上根结点的权值之和。

(3)在F中删除作为新二叉树左,右子树的两课二叉树,同时将新得到的二叉树加入森林F中。

(4)重复(2)和(3),直到F中只含有一棵树为止。这棵树便是Huffman树。

HuffmanTree的存储结构

根据Huffman算法思想可知,HuffmanTree的构造过程,实际上是将由n棵二叉树组成的森林逐渐变成一棵二叉树的过程,因为每次是由两课二叉树合并成为一棵新的二叉树,n棵二叉树的森林经过n-1次合并后产生n-1个分支结点和n个叶子结点,因为一棵有n个叶子结点的HuffmanTree中共有2n-1个结点。如何选定结点结构?如何表示n棵树的森林?如何存储这2n-1个结点的HuffmanTree?这些是构造HuffmanTree首先要解决的问题。

二叉树的存储结构可以选择顺序存储,也可以选择链式存储。当然,选择不同的存储结构,其Huffman算法的实现也不同。鉴于HuffmanTree的结点总数是确定的,所以,下面的算法采用双亲孩子数组表示法。

(1)结点结构。由于在HuffmanTree的狗仔过程中,需要快速存取双亲和左右孩子的信息,所以结点中应存储双亲和左右孩子的位置信息。其中weight为该结点的权值,lchild、rchild和parent分别为该结点的左孩子、右孩子和双亲在数组中的下标(指针)。其结构描述如下:

typedef struct { int weight; int parent,lchild,rchild; }HTNode;

(2)HuffmanTree的存储结构。因为n个权值可以在构造有2n-1个结点的HuffmanTree,则可用一个大小为2n-1的一维数组存储HuffmanTree,数组的每一个分量表示一个结点。数组的初始状态为:前n个分量表示森林F,森林F中的每一棵二叉树只有一个根结点,根结点只有weight域值,其lchild、rchild和parent的域值均为-1(-1表示空);数组的后n-1个分量的weight的域值为0,其lchild、rchild和parent的域值均为-1。

在HuffmanTree构造的过程中,从森林中删除两课被选取的二叉树(根结点的权值最小和次小的树),实际上是把这两棵树的根结点的parent域置为数组中的某一下标(即新二叉树存放在数组中的位置),这样这两棵树的根结点的parent域值不再为-1;往森林中插入一棵新二叉树实际上是把该树的根结点顺序地存放到数组后面相应的位置上,相应的权值为新的二叉树的权值,其lchild、rchild的域值分别为最小二叉树和次小的二叉树在数组中的下标。当HuffmanTree构造完毕后,数组中的2n-1个元素即是HuffmanTree中的所有结点,其中前n个元素是HuffmanTree的n个叶子结点,最后一个分量是HuffmanTree的根结点。HuffmanTree的存储结构描述如下。

typedef HTNode *HuffmanTree; //动态分配数组存储HuffmanTree

typedef HTNode *HuffmanTree; //动态分配数组存储HuffmanTree void select( HuffmanTree HT, int i, int &x1, int &x2 ) { //返回HT的前i个结点中权值最小和权值次小的树的根结点序号 //x1为其中权值较小的序号,x2为其中权值次小的序号 int m1,m2; m1 = m2 = MAXVALUE; //初值为权值最大值 x1 = x2 = 0; for( int j=0; j

你可能感兴趣的:(数据结构)