1、基本概念:霍夫曼(Huffman)树又称最优二叉树或最优搜索树,是一种带权路径长度最短的二叉树。在许多应用中,常常赋给树中结点一个有某种意义的实数,称此实数为该结点的权。从树根结点到该结点之间的路径长度与该结点上权的乘积称为结点的带权路径长度(WPL),树中所有叶子结点的带权路径长度之和称为该树的带权路径长度,通常记为:
2、算法思想:
(1)以权值分别为W1,W2,...Wn的n个结点,构成n课二叉树T1,T2...Tn。其中每棵二叉树Ti是仅有一个权值为Wi的根结点,让它们按权值从小到大的顺序挂在一棵树上;
(2)然后从这些结点中挑选两棵最小的二叉树作为左右子树构造一棵新的二叉树,并且此时的新二叉树的根节点权值为左右子树权值之和;
(3)从上面(第一步中生成的)的那棵顺序树中删掉上面一步的两棵二叉树,把新的二叉树结点放进那棵顺序树中重新排序;
(4)重复(2)、(3)直到最后剩下一颗二叉树为止,这棵二叉树就是Huffman二叉树;
3.C语言代码示例:
HuffmanBiTree.h
#ifndef HUFFMANBITREE_H_H #define HUFFMANBITREE_H_H //Huffman树结点类型 typedef struct HFNODE { int w; struct HFNODE *lchild; struct HFNODE *rchild; }HfNode; //链表结点类型 typedef struct LNODE { struct LNODE *pnext; HfNode *proot; }LNode; //输入函数(控制根结点和权值) void Input(int *n, int *w); //构建huffman二叉树 HfNode *Huffman(int n, int *w); //二叉树结点按权值从小到大的顺序挂在一颗树上 void OrderWeight(LNode **ll, HfNode* ht); //递归中序遍历 void ReOrderTraverse(HfNode *ht, int n); #endif
#include "HuffmanBiTree.h" #include <stdio.h> #include <stdlib.h> //输入函数(控制结点和权值) void Input(int *n, int *w){ int i; printf("请输入结点个数:"); scanf("%d", n); printf("请输入每个结点的权值:\n"); for ( i=0; i<*n; i++ ){ printf("第%d个结点的权值:", i + 1); scanf("%d", &w[i]); } } //构建Huffman二叉树 HfNode *Huffman(int n, int *w){ int i; LNode *l, *p1, *p2; HfNode *hnew, *h, *h1, *h2; l = (LNode*)malloc(sizeof(LNode)); //创建头结点 if ( l == NULL ){ printf("内存分配失败!\n"); exit(EXIT_FAILURE); } l->pnext = NULL; l->proot = NULL; for ( i=0; i<n; i++ ){ hnew = (HfNode*)malloc(sizeof(HfNode)); if ( hnew == NULL ){ printf("内存分配失败!\n"); exit(EXIT_FAILURE); } hnew->w = w[i]; hnew->lchild = NULL; hnew->rchild = NULL; OrderWeight(&l, hnew); } while ( l->pnext->pnext != NULL ){ //至少有两颗二叉树 p1 = l->pnext; p2 = p1->pnext; l->pnext = p2->pnext; h1 = p1->proot; h2 = p2->proot; free(p1); free(p2); h = (HfNode*)malloc(sizeof(HfNode)); if ( h == NULL ){ printf("内存分配失败!\n"); exit(EXIT_FAILURE); } h->w = h1->w + h2->w; h->lchild = h1; h->rchild = h2; OrderWeight(&l, h); } p1 = l->pnext; h = p1->proot; free(l); return h; } //二叉树结点按权值从小到大的顺序挂在一颗树上 void OrderWeight(LNode **l, HfNode *ht){ LNode *ltemp, *lnew, *pl; lnew = (LNode*)malloc(sizeof(LNode)); if ( lnew == NULL ){ printf("内存分配失败!\n"); exit(EXIT_FAILURE); } lnew->proot = ht; lnew->pnext = NULL; pl = *l; ltemp = pl->pnext; while ( ltemp != NULL ){ if ( lnew->proot->w > ltemp->proot->w ){ ltemp = ltemp->pnext; pl = pl->pnext; } else ltemp = NULL; } lnew->pnext = pl->pnext; pl->pnext = lnew; } //递归中序遍历 void ReOrderTraverse(HfNode *ht, int n){ if ( ht != NULL ){ static int WPL = 0; if ( ht->lchild == NULL && ht->rchild == NULL ){ printf("权值为:%d。树的当前层数为:%d\n", ht->w, n); WPL = WPL + n * ht->w; } ReOrderTraverse(ht->lchild, n + 1); ReOrderTraverse(ht->rchild, n + 1); } }
#include <stdio.h> #include "HuffmanBiTree.h" int const M = 20; int main(){ HfNode *head; int n, w[M]; Input(&n, w); head = Huffman(n, w); ReOrderTraverse(head, 1); return 0; }