huffman树【严蔚敏】
来源:互联网 发布:淘宝减肥药 妙瘦 编辑:程序博客网 时间:2024/05/16 07:22
huffman树(最优二叉树)的基本操作及其定义
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
typedef struct { unsigned int weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; // 动态分配数组存储赫夫曼树 typedef char **HuffmanCode; // 动态分配数组存储赫夫曼编码表
int min(HuffmanTree t,int i) { // 函数void select()调用 int j,flag; unsigned int k=UINT_MAX; // 取k为不小于可能的值 for(j=1;j<=i;j++) if(t[j].weight<k&&t[j].parent==0) k=t[j].weight,flag=j; t[flag].parent=1; return flag; }
void select(HuffmanTree t,int i,int &s1,int &s2) { // s1为最小的两个值中序号小的那个 int j; s1=min(t,i); s2=min(t,i); if(s1>s2) { j=s1; s1=s2; s2=j; } }
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n) // 算法6.12 { // w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC int m,i,s1,s2,start; unsigned c,f; HuffmanTree p; char *cd; if(n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用 for(p=HT+1,i=1;i<=n;++i,++p,++w) { (*p).weight=*w; (*p).parent=0; (*p).lchild=0; (*p).rchild=0; } for(;i<=m;++i,++p) (*p).parent=0; for(i=n+1;i<=m;++i) // 建赫夫曼树 { // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 select(HT,i-1,s1,s2); //1>编码字符序号并未发生改变 HT[s1].parent=HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } // 从叶子到根逆向求每个字符的赫夫曼编码 HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); // 分配n个字符编码的头指针向量([0]不用) cd=(char*)malloc(n*sizeof(char)); // 分配求编码的工作空间 cd[n-1]='\0'; // 编码结束符 for(i=1;i<=n;i++) { // 逐个字符求赫夫曼编码 start=n-1; // 编码结束符位置 for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) // 从叶子到根逆向求编码 if(HT[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; HC[i]=(char*)malloc((n-start)*sizeof(char)); // 为第i个字符编码分配空间 strcpy(HC[i],&cd[start]); // 从cd复制编码(串)到HC,//2>注意其中的赋值操作; } free(cd); // 释放工作空间 }
部分详细解释:for(i=n+1;i<=m;++i) // 建赫夫曼树 { // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 select(HT,i-1,s1,s2); HT[s1].parent=HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; }
从图中可以看出先从中取出权值最小的两个将其合并为同一节点的左右子树。
之后是将该两个权值所作之和当做权值进行比较。
每次都得到局部最优解。直至当所有权值均被分配进二叉树之后。完成最优二叉树的构造。
完整代码实现(严蔚敏):
// algo6-1.cpp 求赫夫曼编码。实现算法6.12的程序#include <stdio.h>#include <malloc.h>#include <stdlib.h> #include <string.h>typedef struct { unsigned int weight; unsigned int parent,lchild,rchild; }HTNode,*HuffmanTree; // 动态分配数组存储赫夫曼树 typedef char **HuffmanCode; // 动态分配数组存储赫夫曼编码表 int min(HuffmanTree t,int i) { // 函数void select()调用 int j,flag; unsigned int k=UINT_MAX; // 取k为不小于可能的值 for(j=1;j<=i;j++) if(t[j].weight<k&&t[j].parent==0) k=t[j].weight,flag=j; t[flag].parent=1; return flag; } void select(HuffmanTree t,int i,int &s1,int &s2) { // s1为最小的两个值中序号小的那个 int j; s1=min(t,i); s2=min(t,i); if(s1>s2) { j=s1; s1=s2; s2=j; } } void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n) // 算法6.12 { // w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC int m,i,s1,s2,start; unsigned c,f; HuffmanTree p; char *cd; if(n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用 for(p=HT+1,i=1;i<=n;++i,++p,++w) { (*p).weight=*w; (*p).parent=0; (*p).lchild=0; (*p).rchild=0; } for(;i<=m;++i,++p) (*p).parent=0; for(i=n+1;i<=m;++i) // 建赫夫曼树 { // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 select(HT,i-1,s1,s2); HT[s1].parent=HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } // 从叶子到根逆向求每个字符的赫夫曼编码 HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); // 分配n个字符编码的头指针向量([0]不用) cd=(char*)malloc(n*sizeof(char)); // 分配求编码的工作空间 cd[n-1]='\0'; // 编码结束符 for(i=1;i<=n;i++) { // 逐个字符求赫夫曼编码 start=n-1; // 编码结束符位置 for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) // 从叶子到根逆向求编码 if(HT[f].lchild==c) cd[--start]='0'; else cd[--start]='1'; HC[i]=(char*)malloc((n-start)*sizeof(char)); // 为第i个字符编码分配空间 strcpy(HC[i],&cd[start]); // 从cd复制编码(串)到HC } free(cd); // 释放工作空间 } int main() { HuffmanTree HT; HuffmanCode HC; int *w,n,i; printf("请输入权值的个数(>1):"); scanf("%d",&n); w=(int*)malloc(n*sizeof(int)); printf("请依次输入%d个权值(整型):\n",n); for(i=0;i<=n-1;i++) scanf("%d",w+i); HuffmanCoding(HT,HC,w,n); for(i=1;i<=n;i++) puts(HC[i]); }
0 0
- huffman树【严蔚敏】
- Huffman树&&Huffman编码
- Huffman树
- Huffman 树
- huffman树
- huffman 树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- Huffman树
- huffman 树
- Huffman树
- Huffman树
- gg
- python模块学习
- Jquery懒加载插件
- Android使用SVG小结
- ReactNative text居中问题,和报color 错误问题 ios和android
- huffman树【严蔚敏】
- SPRING中value和ref的简写形式
- oracle本地导入dmp数据
- 用intellij 搭建struts框架完成基本的功能。
- 未来已来:国际电商发展进入云时代
- zend_parse_method_parameters 和 zend_parse_parameters 区别
- 机器学习中的相似性度量
- C语言:数字菱形图案
- Android studio中git使用及git配置路径