/*这是一个哈弗曼编码的完整实例,没什么含量,只是爱X当时闲书上的写的不*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char*  HuffmanCode;/*动态分配数组,存储哈夫曼编码*/
typedef struct
{
unsigned int weight ; /* 用来存放各个结点的权值*/
unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/
}HTNode, * HuffmanTree;   /*动态分配数组,存储哈夫曼树*/
void select(HuffmanTree *ht,int n, int *s1, int *s2)  /*选择霍夫曼树中权值最小的两个结点
并返回他们的序号*/
{
int i;
int min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0) //双亲结点为0
{
min = i;             // 将第一个双亲结点为0的叶结点序号给min
i = n+1;             //将i改为非叶结点
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0)
{                       //比较各叶节点权值与刚才min号结点比较
if((*ht)[i].weight < (*ht)[min].weight)
min = i;      //MIN放权值最小的两个结点序号小的那个
}
}
*s1 = min;                 //s1存放这个小的序号
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1))  //再搜索除s1以外的叶结点
{
min = i;                        //重复上面取最小叶结点的过程
i = n+1;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1))
{
if((*ht)[i].weight < (*ht)[min].weight)
min = i;                  //这个min存放权值第二小的结点序号再给s2
}
}
*s2 = min;
}                                  //最后将最小的两个结点的序号返回
void CrtHuffmanTree(HuffmanTree *ht , int *w, int n)
{ /* w存放已知的n个权值,构造哈夫曼树ht */
int m,i;        //m是结点总数
int s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));  /*0号单元未使用*/
for(i=1;i<=n;i++)
{/*1-n号放叶子结点,初始化*/
(*ht)[i].weight = w[i];
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
}
for(i=n+1;i<=m;i++)
{
(*ht)[i].weight = 0;
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
}    /*非叶子结点初始化*/
/*  ------------初始化完毕!对应算法步骤1---------*/
for(i=n+1;i<=m;i++)    /*创建非叶子结点,建哈夫曼树*/
{  /*在(*ht)[1]~(*ht)[i-1]的范围内就是选择叶子结点
建成一步后,增加了一个双亲节点,则此时需要增加一个结点搜索最小值
由于先前的叶子结点的双亲结点不是0,则不影响搜索
选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/
select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
}
}/*哈夫曼树建立完毕*/
void outputHuffman(HuffmanTree HT, int m) //递归输出霍夫曼树
{
if(m!=0)
{
printf("%d  ", HT[m].weight);
outputHuffman(HT,HT[m].LChild);
outputHuffman(HT,HT[m].RChild);
}
}
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
/*从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码*/
{
char *cd;  //cd是用来存放需要编码的0,1.
int i;
unsigned int c;
int start;
int p;  //指向第i个叶子结点的双亲结点
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));  /*分配n个编码的头指针*hc即使hc[n]
n个编码的头指针0号未使用*/
cd=(char * )malloc(n * sizeof(char ));  /*分配求当前编码的工作空间即是
将那些个0,1存到数组中 0,1以字符形式输出*/
cd[n-1]='\0';   /*从右向左逐位存放编码,首先存放编码结束符*/
for(i=1;i<=n;i++)  /*求n个叶子结点对应的哈夫曼编码*/
{
start=n-1;    /*初始化编码起始指针*/
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*从叶子到根结点求编码*/
if( (*ht)[p].LChild == c)
cd[--start]='0';  /*左分支标0*/
else
cd[--start]='1';  /*右分支标1*/
hc[i]=(char *)malloc((n-start)*sizeof(char));  /*为第i个编码分配空间*/
strcpy(hc[i],&cd[start]);     /*将当前到末尾的霍夫曼编码赋给hc数组*/
}
free(cd);
for(i=1;i<=n;i++)
printf("%d编码为%s\n",(*ht)[i].weight,hc[i]);
}
void main()
{
HuffmanTree HT;
HuffmanCode HC; //定义编码指针 即编码数组,存放所有叶子结点的0,1编码
int *p;
int i,n;      // the number of elements;
int val;    // the weight of a element;
int m;
printf("input the total number of the Huffman Tree:" );
scanf("%d",&n);    //有n个已知权值的结点
p=(int *)malloc((n+1)*sizeof(int));  //分配给权值空间
for(i=1;i<=n;i++)
{
printf("input the %d element's weight:",i);
scanf("%d",&val);
p[i]=val;
}
CrtHuffmanTree(&HT,p,n);
m = 2*n-1;
outputHuffman(HT,m); //输出所有的霍夫曼结点的权值
printf("\n");
CrtHuffmanCode(&HT,&HC,n);  //创建霍夫曼编码,hc是编码数组
} 

哈夫曼树的一个实例,配对严蔚敏或耿国华的数据结构相关推荐

  1. 软件设计师 --哈夫曼树的一个经典问题

    题目如下: 有很多人反应,他们怎么做都做不出正确的答案,结果发过他们画的哈夫曼树的图以后,发现图完全是错误的: 如下图所示: 为什么错误的,因为在遇到有两个权重为17的树的时候,没有遵循选择矮树的原则 ...

  2. 数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)

    目录 什么是哈夫曼树 哈夫曼树的定义 哈夫曼树的构造 图解操作 代码实现 代码解析 哈夫曼树的特点 哈夫曼编码 不等长编码 二叉树用于编码 哈夫曼编码实例 什么是哈夫曼树 我们先举个例子: 要将百分制 ...

  3. Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树

    Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 文章目录 Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 0x00 摘要 0x01 背景概念 1.1 词向量 ...

  4. c语言霍夫曼函数,使用C语言详解霍夫曼树数据结构

    1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,--,kj, 使得 ki是ki+1 的双亲(1<=i 从 k1 到 kj 所经过的分支数称为这两点之间的路径长度,它 ...

  5. 字符串哈夫曼树C语言,C语言实现哈夫曼树的方法

    本文实例为大家分享了C语言实现哈夫曼树的具体代码,供大家参考,具体内容如下 准备工作: 1.定义一个结构体,表示一个节点.其中,这个结构体有4个成员变量,分别表示是这个节点的权值,父节点及左右子节点的 ...

  6. 【算法学习笔记】哈夫曼树的构建和哈夫曼编码的实现代码

    介绍 哈夫曼(Haffman)这种方法的基本思想如下: ①由给定的n个权值{W1,W2,-,Wn}构造n棵只有一个叶子结点的二叉树,从而得到一个二叉树的集合F={T1,T2,-,Tn}. ②在F中选取 ...

  7. 数据结构(哈夫曼树,哈夫曼编码)入门篇,JAVA实现

    什么是哈夫曼树 哈夫曼树就是一种最优判定树,举个例子,如下一个判断逻辑 if(s<60) g=1; else if(s<70) g=2 else if(s<80) g=3 else ...

  8. 一文看懂哈夫曼树与哈夫曼编码

    转自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299884.html 在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUF ...

  9. POJ-Fence Repair 哈夫曼树

    哈夫曼树,一个很耳熟的数据结构课上的内容.是用来处理编码的,准确的说是能够去压缩编码,本身是一种无损的压缩凡是,就是对于给定的字符做一个统计,然后根据统计构建一个长短不一的映射表,再根据这个映射表来恢 ...

最新文章

  1. 环境微生物期刊—Bioresource Technology
  2. Qt 中 QXml/QDom*** api设计吐槽
  3. [蓝桥杯2018初赛]递增三元组-双指针,枚举,排序,前缀和
  4. 一个关于人工智能实现的讨论
  5. python logging模块的作用及应用场景_Python logging模块原理解析及应用
  6. python 代理类型说明
  7. css设置字体的行数,超出显示...
  8. linux下688权限,Linux shell脚本笔记
  9. spring cloud构建互联网分布式微服务云平台-服务提供与调用
  10. 路由入口与vue布局入口
  11. Facebook TSDB论文翻译
  12. java代码随机取名字
  13. 「MySQL」- 基础增删改查
  14. 素数处理-埃拉托色尼筛选法(埃式筛)
  15. 树莓派hc sr501 c语言,树莓派人体红外感应模块HC-SR501安装配置
  16. 遗传算法(进化类算法)中的选择,交叉,变异等一系列问题解析(二)
  17. ipv6一致性(packet too big)测试
  18. java计算机毕业设计高考报考指南网站源码+mysql数据库+系统+lw文档+部署
  19. php v11跟v14区别,独家揭秘真相戴森v11absolute和fluffy哪个好?有啥区别?老司机指教诉说...
  20. python重新编号功能_Python:PDB文件中原子和残基重新编号

热门文章

  1. Re0:Java编程系列-3 进阶排序思维分析与对比
  2. 探索微前端的场景极限
  3. 经典面试题---【第一档】
  4. 云服务器挂载vnpy,VNPY 价差交易模块的使用学习
  5. 概率论基础-条件概率、全概率公式、贝叶斯公式
  6. 好用压缩软件推荐 7 zip
  7. 自己动手制作MUD客户端服务程序
  8. 截止至2022/8/23,CUDA ToolKit对应Nvdia驱动
  9. js监听浏览器焦点事件
  10. 视频监控项目--友善之臂---阿里云---QT---mjpg-streamer