
#include<stdio.h>#include<stdlib.h>#define MAX 100typedef struct node{ int w; struct node *lchild,*rchild;}BiTNode, *BiTree;BiTree CreateHufferman(int num[], int n);int GetWPL(BiTree T, int pathLen);void GetCode(BiTree T, int pathLen);int main() {/*52 5 7 9 13*/ int n,num[MAX]; BiTree HfmTree; int i; int tmp; // 输入个数 do{ printf("权重个数,最多能输入%d个\n>>> ", MAX); scanf("%d", &n); } while (n>MAX); //检查输入是否合法 // 输入数组 printf("输入权重数组(%d个)\n>>> ", n); for (i=0; i<n; i++) { scanf("%d", &num[i]); } // 创造 HfmTree = CreateHufferman(num, n); // 计算WPL tmp = GetWPL(HfmTree, 0); //根结点的路径长度为0 printf("\nWPL:%d\n", tmp); // 哈夫曼编码 printf("权重\t哈夫曼编码"); GetCode(HfmTree, 0); //根结点的路径长度为0 printf("\n"); return 0;}BiTree CreateHufferman(int num[], int n) { BiTree *tmp; //BiTree[]用于存放n个子树 BiTNode p; //结点 int k1,k2; //k1为最小的下标,k2为次小的下标 int i,j; //创建一个BiTree[]来存n个子树 tmp = (BiTree *)malloc(sizeof(BiTree) * n); //创建n个结点,每个结点即是树的根,放到tmp[]中统一管理 for (i=0; i<n; i++) { tmp[i] = (BiTNode *)malloc(sizeof(BiTNode)); if (!tmp[i]) exit(0); tmp[i]->w = num[i]; tmp[i]->lchild = tmp[i]->rchild = NULL; } //构造哈夫曼树,循环n-1次 for (i=1; i<n; i++) { //找出tmp[0]至tmp[n]中的前两个 k1 = -1; //k1未选 for (j=0; j<n; j++) { if (tmp[j]!=NULL && k1==-1) { //找到了第一个 k1 = j; continue; //找k2 } if (tmp[j]!=NULL) { //找到了第二个 k2 = j; break; //退出 } } //找出最小的、次小的结点 for (j=k2; j<n; j++) { //从k2开始 if (tmp[j]==NULL) continue; //空树,进入下一轮循环 // 和当前k1、k2比较 if (tmp[j]->w < tmp[k1]->w) { //先和最小的k1比较 // 即 [j] < [k1],j是当前的最小 k2 = k1; //△原来最小的变成了次小 k1 = j; //最小的变成了j } else if (tmp[j]->w < tmp[k2]->w) { //和次小的比较 // 即[k1] < [j] < [k2] k2 = j; //次小的为j } } //合并k1,k2 p = (BiTNode *)malloc(sizeof(BiTNode)); if (!p) exit(0); p->w = tmp[k1]->w + tmp[k2]->w; p->lchild = tmp[k1]; p->rchild = tmp[k2]; tmp[k1] = p; // 新结点的放到k1的位置 tmp[k2] = NULL; // k2位置为空 } free(tmp); //删除动态建立的数组tmp[] //它只是一个BiTNode *的指针数组,而所指结点(即新建的哈夫曼结点)是不会被删除的! return p; //返回哈夫曼树的根结点}int GetWPL(BiTree T, int pathLen) { // 叶子结点 if (T->lchild==NULL && T->rchild==NULL) { return T->w * pathLen; } return GetWPL(T->lchild, pathLen+1) + GetWPL(T->rchild, pathLen+1);}void GetCode(BiTree T, int pathLen) { static char tmp[2*MAX-1]; //存储编码的结果 int i; // 叶子结点 if (T->lchild==NULL && T->rchild==NULL) { printf("\n%d\t", T->w); //结点值 for (i=0; i<pathLen; i++) { //编码值 printf("%c", tmp[i]); } return ; } //往左走 tmp[pathLen] = '0'; GetCode(T->lchild, pathLen+1); //往右走 tmp[pathLen] = '1'; GetCode(T->rchild, pathLen+1);}