给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,则称该二叉树为哈夫曼树,也被称为最优二叉树。
1、路径—从树中一个结点到另一个结点之间的分支构成这两个结点间的路径
结点路径长度—两结点间路径上的分支数
树的路径长度—根节点到每个结点路径长度之和(TL)
TL = 1+1+2+2+3+3+4+4 = 20
2、权—结点所赋的值
结点带权路径长度—从根节点到该结点间路径长度和权的乘积
树的带权路径长度—结点之和(WPL)
WPL = 7*2+5*2+2*2+4*2 = 36
(构造哈夫曼树时首先选择权值小的叶子结点,权越大离根越近)
3、哈夫曼编码
二、代码展示利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码。
#include#define MAX_SIZE 1000 typedef struct NODE Node; struct NODE { int weight;//结点权值 int parent,lchild,rchild; }; //初始化结点 void initNode(Node &node,int weight,int parent,int lchild,int rchild) { node.weight = weight; node.parent = parent; node.lchild = lchild; node.rchild = rchild; } void createHuffmanTree(Node *node,int *a,int n) //n为叶子结点个数 { int i,j,m1,m2,x1,x2,total; for(i = 0;i < n;i++) { initNode(node[i],a[i],-1,-1,-1); } total = n*2-1;//哈夫曼树所有结点的个数 for(i = n;i < total;i++) { m1 = 100; m2 = m1; x1 = x2 =0; for(j = 0;j < i;j++) { if(node[j].parent == -1) { if(node[j].weight < m1) { m2 = m1; x2 = x1; m1 = node[j].weight; x1 = j; } else if(node[j].weight < m2) { m2 = node[j].weight; x2 = j; } } } node[x1].parent = i; node[x2].parent = i; initNode(node[i],m1+m2,-1,x1,x2); } } //哈夫曼编码 void huffmanCode(Node *node,int child,int *str) { int i,parent,j = 0,e; parent = node[child].parent;//父结点 while(parent != -1) { if(node[parent].lchild == child)//若此结点为该父结点的左子结点,0入数组,否则1入数组 { str[j++] = 0; } else { str[j++] = 1; } child = parent; parent = node[child].parent; } e = j; for(j = e-1;j >= 0;j--) printf("%d",str[j]); printf("n"); } int main() { Node node[MAX_SIZE]; int a1[MAX_SIZE];//存放权值 int a2[MAX_SIZE];//存放哈夫曼编码 int n,i,j,e; printf("请输入叶子结点的个数:"); scanf("%d",&n); for(i = 0;i < n;i++) { scanf("%d",&a1[i]); } createHuffmanTree(node,a1,n); for(i = 0;i < n;i++) { huffmanCode(node,i,a2); } return 0; }
请输入叶子结点的个数:8 15 14 1 25 6 24 26 12 101 100 11000 00 11001 111 01 1101



