当前位置: 首页 > news >正文

服务器网站配置/百度网盘搜索引擎入口官网

服务器网站配置,百度网盘搜索引擎入口官网,shopify建站,网站开发进度计划书哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树或者赫夫曼树,它是最优二叉树。 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。 (01…

哈夫曼树的介绍

Huffman Tree,中文名是哈夫曼树或霍夫曼树或者赫夫曼树,它是最优二叉树。

定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。 

(01) 路径和路径长度

定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。 

(02) 结点的权及带权路径长度

定义:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。 

(03) 树的带权路径长度

定义:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。 

哈夫曼树的解析:

假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,哈夫曼树的构造规则为:

1. 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点); 
2. 在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和; 
3. 从森林中删除选取的两棵树,并将新树加入森林; 
4. 重复(02)、(03)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。


以{5,6,7,8,15}为例,来构造一棵哈夫曼树。

第1步:创建森林,森林包括5棵树,这5棵树的权值分别是5,6,7,8,15。 
第2步:在森林中,选择根节点权值最小的两棵树(5和6)来进行合并,将它们作为一颗新树的左右孩子(谁左谁右无关紧要,这里,我们选择较小的作为左孩子),并且新树的权值是左右孩子的权值之和。即,新树的权值是11。 然后,将"树5"和"树6"从森林中删除,并将新的树(树11)添加到森林中。 
第3步:在森林中,选择根节点权值最小的两棵树(7和8)来进行合并。得到的新树的权值是15。 然后,将"树7"和"树8"从森林中删除,并将新的树(树15)添加到森林中。 
第4步:在森林中,选择根节点权值最小的两棵树(11和15)来进行合并。得到的新树的权值是26。 然后,将"树11"和"树15"从森林中删除,并将新的树(树26)添加到森林中。 
第5步:在森林中,选择根节点权值最小的两棵树(15和26)来进行合并。得到的新树的权值是41。 然后,将"树15"和"树26"从森林中删除,并将新的树(树41)添加到森林中。 
此时,森林中只有一棵树(树41)。这棵树就是我们需要的哈夫曼树!

哈夫曼树的基本操作:

 在上述存储结构上实现的哈夫曼算法可大致描述为(设T的类型为HuffmanTree):
 (1)初始化
     将T[0..m-1]中2n-1个结点里的三个指针均置为空(即置为-1),权值置为0。
 (2)输入
     读入n个叶子的权值存于向量的前n个分量(即T[0..n-1])中。它们是初始森林中n个孤立的根结点上的权值。
 (3)合并
     对森林中的树共进行n-1次合并,所产生的新结点依次放人向量T的第i个分量中(n≤i≤m-1)。每次合并分两步:
     ①在当前森林T[0..i-1]的所有结点中,选取权最小和次小的两个根结点[p1]和T[p2]作为合并对象,这里0≤p1,p2≤i-1。
     ② 将根为T[p1]和T[p2]的两棵树作为左右子树合并为一棵新的树,新树的根是新结点T[i]。具体操作:
  将T[p1]和T[p2]的parent置为i,
  将T[i]的lchild和rchild分别置为p1和p2
  新结点T[i]的权值置为T[p1]和T[p2]的权值之和。
  注意:
     合并后T[pl]和T[p2]在当前森林中已不再是根,因为它们的双亲指针均已指向了T[i],所以下一次合并时不会被选中为合并对象。


哈夫曼树的存储结构:

<span style="font-size:18px;">/*
哈夫曼树的存储结构,它也是一种二叉树结构,
这种存储结构既适合表示树,也适合表示森林。
*/
typedef struct Node
{
int weight;                //权值
int parent;                //父节点的序号,为-1的是根节点
int lchild,rchild;         //左右孩子节点的序号,为-1的是叶子节点
}HTNode,*HuffmanTree;          //用来存储哈夫曼树中的所有节点
typedef char **HuffmanCode;    //用来存储每个叶子节点的哈夫曼编码</span>

根据哈夫曼树的构建步骤,写出构建哈夫曼树的代码如下

<span style="font-size:18px;">/*
根据给定的n个权值构造一棵赫夫曼树,wet中存放n个权值
*/
HuffmanTree create_HuffmanTree(int *wet,int n)
{
//一棵有n个叶子节点的赫夫曼树共有2n-1个节点
int total = 2*n-1;
HuffmanTree HT = (HuffmanTree)malloc(total*sizeof(HTNode));
if(!HT)
{
printf("HuffmanTree malloc faild!");
exit(-1);
}
int i;//以下初始化序号全部用-1表示,
//这样在编码函数中进行循环判断parent或lchild或rchild的序号时,
//不会与HT数组中的任何一个下标混淆//HT[0],HT[1]...HT[n-1]中存放需要编码的n个叶子节点
for(i=0;i<n;i++)
{
HT[i].parent = -1;
HT[i].lchild = -1;
HT[i].rchild = -1;
HT[i].weight = *wet;
wet++;
}//HT[n],HT[n+1]...HT[2n-2]中存放的是中间构造出的每棵二叉树的根节点
for(;i<total;i++)
{
HT[i].parent = -1;
HT[i].lchild = -1;
HT[i].rchild = -1;
HT[i].weight = 0;
}int min1,min2; //用来保存每一轮选出的两个weight最小且parent为0的节点
//每一轮比较后选择出min1和min2构成一课二叉树,最后构成一棵赫夫曼树
for(i=n;i<total;i++)
{
select_minium(HT,i,min1,min2);
HT[min1].parent = i;
HT[min2].parent = i;
//这里左孩子和右孩子可以反过来,构成的也是一棵赫夫曼树,只是所得的编码不同
HT[i].lchild = min1;
HT[i].rchild = min2;
HT[i].weight =HT[min1].weight + HT[min2].weight;
}
return HT;
}</span>

上述代码中调用到了select_minium()函数,它表示从集合中选出两个最小的二叉树,下面列出两种求两个最小值的方法。

方法一代码如下:

<span style="font-size:18px;">/*
从HT数组的前k个元素中选出weight最小且parent为-1的两个,分别将其序号保存在min1和min2中
*/
void select_minium(HuffmanTree HT,int k,int &min1,int &min2)
{min1 = min(HT,k);min2 = min(HT,k);
}</span>

这里调用到的min()函数代码如下:

<span style="font-size:18px;">/*
从HT数组的前k个元素中选出weight最小且parent为-1的元素,并将该元素的序号返回
*/
int min(HuffmanTree HT,int k)
{int i = 0;int min;        //用来存放weight最小且parent为-1的元素的序号int min_weight; //用来存放weight最小且parent为-1的元素的weight值//先将第一个parent为-1的元素的weight值赋给min_weight,留作以后比较用。
//注意,这里不能按照一般的做法,先直接将HT[0].weight赋给min_weight,
//因为如果HT[0].weight的值比较小,那么在第一次构造二叉树时就会被选走,
//而后续的每一轮选择最小权值构造二叉树的比较还是先用HT[0].weight的值来进行判断,
//这样又会再次将其选走,从而产生逻辑上的错误。while(HT[i].parent != -1)i++;min_weight = HT[i].weight;min = i;//选出weight最小且parent为-1的元素,并将其序号赋给minfor(;i<k;i++){if(HT[i].weight<min_weight && HT[i].parent==-1){min_weight = HT[i].weight;min = i;}}//选出weight最小的元素后,将其parent置1,使得下一次比较时将其排除在外。HT[min].parent = 1;return min;
}</span>


方法二代码如下:

<span style="font-size:18px;">/*
从HT数组的前k个元素中选出weight最小且parent为-1的两个,分别将其序号保存在min1和min2中
*/
void select_minium(HuffmanTree HT,int k,int &min1,int &min2)
{
int i = 0;Int tempMin;
while(HT[i].parent != -1)
i++;
min1 = HT[i].weight;
while(HT[i].parent != -1)
i++;
min2 = HT[i].weight;
if(min1>min2)
{
tempMin = min1;
min1=min2;
Min2=tempMin;
}
//选出weight最小且parent为-1的元素,并将其序号赋给min
for(;i<k;i++)
{
if(HT[i].weight<min1 && HT[i].parent==-1)//min1始终保存最小的,min2保存第二小的数据
{
min2 = min1;
min1 = HT[i].weight;
}else if(HT[i].weight<min2 && HT[i].parent==-1)
{
Min2 = HT[i].weight;
}
}
}</span>


构建了赫夫曼树,便可以进行赫夫曼编码了,要求赫夫曼编码,就需要遍历出从根节点到叶子节点的路径,下面给出两种遍历赫夫曼树求编码的方法。

1、 采用从叶子节点到根节点逆向遍历求每个字符的赫夫曼编码,代码如下

<span style="font-size:18px;">/*
从叶子节点到根节点逆向求赫夫曼树HT中n个叶子节点的赫夫曼编码,并保存在HC中
*/
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n)
{
//用来保存指向每个赫夫曼编码串的指针
HC = (HuffmanCode)malloc(n*sizeof(char *));
if(!HC)
{
printf("HuffmanCode malloc faild!");
exit(-1);
}//临时空间,用来保存每次求得的赫夫曼编码串
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1
//外加一个'\0'结束符,因此分配的数组长度最长为n即可
char *code = (char *)malloc(n*sizeof(char));
if(!code)
{
printf("code malloc faild!");
exit(-1);
}code[n-1] = '\0';  //编码结束符,亦是字符数组的结束标志
//求每个字符的赫夫曼编码
int i;
for(i=0;i<n;i++)
{
int current = i;           //定义当前访问的节点
int father = HT[i].parent; //当前节点的父节点
int start = n-1;           //每次编码的位置,初始为编码结束符的位置
//从叶子节点遍历赫夫曼树直到根节点
while(father != -1)
{
if(HT[father].lchild == current)   //如果是左孩子,则编码为0
code[--start] = '0';   
else                              //如果是右孩子,则编码为1      
code[--start] = '1';
current = father;
father = HT[father].parent;
}//为第i个字符的编码串分配存储空间
HC[i] = (char *)malloc((n-start)*sizeof(char));
if(!HC[i])
{
printf("HC[i] malloc faild!");
exit(-1);
}
//将编码串从code复制到HC
strcpy(HC[i],code+start);
}free(code); //释放保存编码串的临时空间
}</span>

2采用从根节点到叶子节点无栈非递归遍历赫夫曼树,求每个字符的赫夫曼编码,代码如下

<span style="font-size:18px;">/*
从根节点到叶子节点无栈非递归遍历赫夫曼树HT,求其中n个叶子节点的赫夫曼编码,并保存在HC中
*/
void HuffmanCoding2(HuffmanTree HT,HuffmanCode &HC,int n)
{
//用来保存指向每个赫夫曼编码串的指针
HC = (HuffmanCode)malloc(n*sizeof(char *));
if(!HC)
{
printf("HuffmanCode malloc faild!");
exit(-1);
}//临时空间,用来保存每次求得的赫夫曼编码串
//对于有n个叶子节点的赫夫曼树,各叶子节点的编码长度最长不超过n-1
//外加一个'\0'结束符,因此分配的数组长度最长为n即可
char *code = (char *)malloc(n*sizeof(char));
if(!code)
{
printf("code malloc faild!");
exit(-1);
}int cur = 2*n-2;    //当前遍历到的节点的序号,初始时为根节点序号
int code_len = 0;   //定义编码的长度//构建好赫夫曼树后,把weight用来当做遍历树时每个节点的状态标志
//weight=0表明当前节点的左右孩子都还没有被遍历
//weight=1表示当前节点的左孩子已经被遍历过,右孩子尚未被遍历
//weight=2表示当前节点的左右孩子均被遍历过
int i;
for(i=0;i<cur+1;i++)
{
HT[i].weight = 0;  
}//从根节点开始遍历,最后回到根节点结束
//当cur为根节点的parent时,退出循环
while(cur != -1)
{
//左右孩子均未被遍历,先向左遍历
if(HT[cur].weight == 0)  
{
HT[cur].weight = 1;    //表明其左孩子已经被遍历过了
if(HT[cur].lchild != -1) 
{   //如果当前节点不是叶子节点,则记下编码,并继续向左遍历
code[code_len++] = '0';
cur = HT[cur].lchild;
}
else
{   //如果当前节点是叶子节点,则终止编码,并将其保存起来
code[code_len] = '\0';
HC[cur] = (char *)malloc((code_len+1)*sizeof(char));
if(!HC[cur])
{
printf("HC[cur] malloc faild!");
exit(-1);
}
strcpy(HC[cur],code);  //复制编码串
}
}//左孩子已被遍历,开始向右遍历右孩子
else if(HT[cur].weight == 1)  
{
HT[cur].weight = 2;   //表明其左右孩子均被遍历过了
if(HT[cur].rchild != -1)
{   //如果当前节点不是叶子节点,则记下编码,并继续向右遍历
code[code_len++] = '1';
cur = HT[cur].rchild;
}
}//左右孩子均已被遍历,退回到父节点,同时编码长度减1
else
{
HT[cur].weight = 0;
cur = HT[cur].parent;
--code_len;
}}
free(code);
}</span>

http://www.lbrq.cn/news/968203.html

相关文章:

  • 徐州库云平台/网站seo排名优化工具在线
  • 厦门建设银行网站首页/枸橼酸西地那非片的功效与作用
  • 网上商城网站设计/农产品推广方案
  • web用框架做网站步骤/网络营销的渠道有哪些
  • 2017年免费建网站/网站关键词快速排名服务
  • 广告型网站建设/今日新闻快报
  • 无锡网站开发平台/游戏加盟
  • 自助模板网站建设做seo/今天新闻
  • 如何做网站链接分析/电商平台推广
  • 做网站撘框架/seo有哪些优化工具
  • 国外的做的比较优秀的网站有哪些/网址域名ip解析
  • 网站多种语言是怎么做的/手机百度账号登录入口
  • 免费发布出租房信息网站/seo排名工具外包
  • 腾讯网站建设费用/新闻稿营销
  • 北京网站建设升上去/天津seo诊断
  • 都匀市城乡建设局网站/2023年8月新冠又来了
  • 做网站毕设答辩问题/网站名称查询
  • 建设银行网站 查余额查询/新闻稿撰写
  • 现代化专业群建设专题网站护理专业/百度我的订单app
  • 坪地做网站/seo排名哪家有名
  • 广州口碑好的网站建设定制/崇左网站建设
  • 香港网站域名查询/站长工具 忘忧草
  • 零食天堂 专做零食推荐的网站/百度seo收录软件
  • 番禺哪里有做网站的公司/手机刷网站排名软件
  • 网片生产厂家/百度网站优化
  • wordpress登陆页面404/360优化大师app
  • 做网站需要什么图片/铁岭网站seo
  • 网站开发成本包括/windows优化大师提供的
  • 企业设计网站公司哪家好/网络营销事件
  • 做淘宝图的素材搜索网站/天天seo伪原创工具
  • 一款基于PHP开发的不良事件上报系统源码,适用于医院安全管理。系统提供10类事件类别、50余种表单,支持在线填报、匿名上报及紧急报告。
  • 代码随想录算法训练营十八天|二叉树part08
  • HTML 入门教程:从零开始学习网页开发基础
  • C#.NET BackgroundService 详解
  • 面向向量检索的教育QA建模:九段日本文化研究所日本语学院的Prompt策略分析(6 / 500)
  • LeafletJS 进阶:GeoJSON 与动态数据可视化