数据结构之最优二叉树

数据结构之最优二叉树

  • 1、最优二叉树
  • 2、哈夫曼编码

  数据结构是程序设计的重要基础,它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所涉及的数据选择适当的逻辑结构、存储结构及其相应的操作方法,为提高利用计算机解决问题的效率服务。
  数据结构是指数据元素的集合及元素间的相互关系和构造方法。元素之间的相互关系是数据的 逻辑结构,数据元素及元素之间关系的存储称为 存储结构(或物理结构)。数据结构按照逻辑关系的不同分为 线性结构非线性结构两大类,其中,非线性结构又可分为树结构和图结构。
  树结构是一种非常重要的非线性结构,该结构中的一个数据元素可以有两个或两个以上的直接后继元素,树可以用来描述客观世界中广泛存在的层次结构关系。
  二叉树是 n(n≥0)个结点的有限集合,它或者是空树(n=0),或者是由一个根结点及两棵不相交的且分别称为左、右子树的二叉树所组成。

1、最优二叉树

  最优二叉树又称为哈夫曼树,它是一类带权路径长度最短的树。路径是从树中一个结点到另一个结点之间的通路,路径上的分支数目称为路径长度。
  树的路径长度是从树根到每一个叶子之间的路径长度之和。结点的带权路径长度为从该结点到树根之间的路径长度与该结点权值的乘积。
  树的带权路径长度为树中所有叶子结点的带权路径长度之和,记为
W P L = Σ k = 1 n w k l k WPL={\huge\Sigma}^n_{k=1}{\large w}_k {\large l}_k WPL=Σk=1nwklk
其中,n 为带权叶子结点数目,wk 为叶子结点的权值,lk为叶子结点到根的路径长度。
  哈夫曼树是指权值为 w1,w2,···,wn 的n个叶子结点的二又树中带权路径长度最小的二叉树。
  例如,下图所示的具有4个叶子结点的二叉树,其中以图 (b) 所示的二叉树带权路径长度最小。
在这里插入图片描述

  那么如何构造最优二叉树呢? 构造最优二叉树的哈夫曼算法如下。
  (1)根据给定的n个权值 {w1,w2,···,wn},构成n颗二叉树的集合F= (T1,T2,···,Tn},其中,每棵树 Ti 中只有一个带权为 wi 的根结点,其左、右子树均空。
  (2)在F中选取两棵权值最小的树作为左、右子树构造一棵新的二叉树,置新构造二叉树的根结点的权值为其左、右子树根结点的权值之和。
  (3)从F中删除这两棵树,同时将新得到的二叉树加入到F中。
  重复(2)、(3) 步,直到 F 中只含一棵树时为止,这棵树便是最优二叉树(哈夫曼树)。
  由此算法可知,以选中的两棵子树构成新的二叉树,哪个作为左子树,哪个作为右子树,并没有明确。所以,具有n 个叶子结点的权值为 w1,w2,···,wn 的最优二叉树不唯一,但其 WPL 值是唯一确定的。
  当给定了 n 个权值后,构造出的最优二叉树中的结点数目 m 就确定了,即 m=2×n-1,所以可用一维的结构数组来存储最优二叉树,下面举例说明。

#define MAXLEAFNUM 50						/*最优二叉树中的最多叶子数目*/
typedef struct nodef{char ch;								/*结点表示的字符,对于非叶子结点,此域不用*/int weight;								/*结点的权值*/int parent;								/*结点的父结点的下标,为0时表示无父结点*/int lchild,rchild;						/*结点的左、右孩子结点的下标,为0 时表示无孩子结点*/
}HuffmanTree[2*MAXLEAFNUM];
typedef char* HuffmanCode[MAXLEAFNUM+1];

  【函数】创建最优二叉树。

void createHTree(HuffmanTree HT, char *c, int *w,int n)
/*数组 c[0..n-1]和 w[0..n-1]存放了n个字符及其概率,构造哈夫曼树HT*/
{int i,sl,s2;if (n <= 1) return;for(i=l; i<-n; i++){ /*根据n个权值构造n只有根结点的二叉树*/HT[i].ch = c[i-l]; HT[i].weight = w[i-l];HT[i].parent=HT[i].lchild=HT[i].rchild=0;}for(;i<2*n;++i) { /*初始化*/HT[i].parent=0;HT[i].lchild=0; HT[i].rchild=0;}for(i= n+l; i<2*n; i++)/*从HT[l..i-1]中选择 parent 为0且weight最小的两棵树,其序号为 s1和s2*/select(HT,i-1,s1,s2);HT[sl].parent = i;HT[s2].parent = i;HT[i].lchild = s1;HT[i].rchild = s2;HT[i].weight = HT[sl].weight + HT[s2].weight;}/*for*/
}/* createHTree*/

2、哈夫曼编码

  若对每个字符编制相同长度的二进制码,则称为等长编码。例如,英文字符集中的 26个字符可采用5 位二进制位串表示,按等长编码格式构造一个字符编码表。发送方按照编码表对信息原文进行编码后送出电文,接收方对接收到的二进制代码按每 5位一组进行分割,通过字符的编码表即可得到对应字符,实现译码。
  等长编码方案的实现方法比较简单,但对通信中的原文进行编码后,所得电文的码串过长不利于提高通信效率,因此希望缩短码串的总长度。如果对每个字符设计长度不等的编码,且让电文中出现次数较多的字符采用尽可能短的编码,那么传送的电文码串总长度则可减少。
  如果要设计长度不等的编码,必须满足下面的条件:任一字符的编码都不是另一个字符的编码的前缀,这种编码也称为前缀码。对给定的字符集 D={d1,d2,···,dn} 及字符的使用频率W={w1,w2,···,wn},构造其最优前缀码的方法为: 以d1,d2,···,dn 作为叶子结点,w1,w2,···,wn 作为叶子结点的权值,构造出一棵最优二叉树,然后将树中每个结点的左分支标上 0,右分支标上1,则每个叶子结点代表的字符的编码就是从根到叶子的路径上的0、1组成的串。
  例如,设有字符集{a,b,c,d,e}及对应的权值集合{0.30,0.25,0.15,0.22,0.08},按照构造最优二叉树的哈夫曼方法:先取字符 c和e所对应的结点构造一棵二叉树(根结点的权值为c和e的权值之和),然后与 d 对应的结点分别作为左、右子树构造二叉树,之后选a 和b所对应的结点作为左、右子树构造二叉树,最后得到的最优二叉树 (哈夫曼树)如下图所示。其中,字符a的编码为 00,字符b、c、d、e的编码分别为 01、100、11、101。
前缀编码示例

  译码时就从树根开始,若编码序列中当前编码为 0,则进入当前结点的左子树;为1 则进入右子树,到达叶子时一个字符就翻译出来了,然后再从树根开始重复上述过程,直到编码序列结束。例如,若编码序列101110000100 对应的字符编码采用上图所示的树进行构造,则可翻译出字符序列"edaac"。
  【函数】根据给定的哈夫曼树,从每个叶子结点出发追溯到树根,逆向找出最优二叉树中叶子结点的编码。

void HuffmanCoding(HuffmanTree HT, HuffmanCode HC,int n)
/*n个叶子结点在哈夫曼树HT中的下标为 1~n,第i(l≤i≤n)个叶子的编码存放HC[i]中*/
{char *cd; int i, start, c, f;if(n <= 1) return;cd =(char *)malloc(n*sizeof(char));cd[n-1]='\0';for(i= l; i<= n;+){start = n-l;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));strcpy(HC[il,&cd[start]);}/*for*/free(cd);
}/*HuffmanCoding*/

  利用哈夫曼树译码的过程为:从根结点出发,按二进制位串中的0和1确定是进入左分支还是右分支,当到达叶子结点时译出一个字符。若位串未结束,则回到根结点继续上述译码过程,直到位串结束。
  【函数】用最优二又树进行译码

void Decoding(HuffmanTree HT,int n,char *buf) 
/*利用具有n个叶子结点的最优二叉树(存储在数组 HT 中) 进行译码,叶子的下标为 1~n*/
/*buff 指向二进制位串编码序列*/
{int p=2*n-1;while (*buff){if((*buff) == '0') p = HT[p].lchild;		/*进入左分支*/else p = HT[p].rchild;						/*进入右分支*/if(HT[p].lchild==0 && HT[p].rchild==0){		/*到达一个叶子结点*/printf("%c", HT[p].ch);p=2*n-1;								/*回到树根*/}/*if*/buff++;}/*while*/
}/*Decoding*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/424241.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人云服务器docker搭建部署前后端应用-myos

var code "87c5235c-b551-45bb-a5e4-9593cb104663" mysql、redis、nginx、java应用、前端应用部署 本文以单台云服务器为例&#xff1a; 1. 使用腾讯云服务器 阿里或其他云服务器皆可&#xff0c;类似 安装系统&#xff0c;现在服务器系统都集成安装了docker镜像&a…

GPTs Store 推荐的学术类应用,效果怎么样?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 哪些 GPTs &#xff0c;会令我们眼前一亮&#xff1f; 最近 GPTs Store 已经正式发布&#xff0c;提供了推荐应用和各分类板块目前的热门趋势…

网络通信(15)-C#TCP客户端掉线重连实例

本文上接前面的文章使用Socket在C#语言环境下完成TCP客户端的掉线重连实例。 掉线重连需要使用心跳包发送测试网络的状态,进而进入重连循环线程。 前面实例完成的功能: 客户端与服务器连接,实现实时刷新状态。 客户端接收服务器的数据。 客户端发送给服务器的数据。 客…

初识Vue.js开发

一、Vue在前端重要性 1.认识vue Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式 JavaScript框架。 全称是Vue.js或者Vuejs&#xff1b;它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff1b…

【DevOps】Jenkins Extended E-mail 邮件模板添加自定义变量

文章目录 1、配置Jenkins邮箱2、配置告警模板1、配置Jenkins邮箱 略 2、配置告警模板 自定义变量:DYSK_PYTEST_STATUS // Uses Declarative syntax to run commands inside a container. pipeline {agent {kubernetes {cloud "kubernetes" //选择名字是kuberne…

【算法】选择最佳路线(超级源点)

题目 有一天&#xff0c;琪琪想乘坐公交车去拜访她的一位朋友。 由于琪琪非常容易晕车&#xff0c;所以她想尽快到达朋友家。 现在给定你一张城市交通路线图&#xff0c;上面包含城市的公交站台以及公交线路的具体分布。 已知城市中共包含 n 个车站&#xff08;编号1~n&…

数据仓库简介

一、数仓概念 数据仓库&#xff0c;英文名称为Data Warehouse&#xff0c;可简写为DW或DWH。数据仓库&#xff0c;是为企业所有级别的决策制定过程&#xff0c;提供所有类型数据支持的战略集合。它是单个数据存储&#xff0c;出于分析性报告和决策支持目的而创建。 为需要业务…

如何使用固定公网地址访问多个本地Nginx服务搭建的网站

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 本文主要介绍如何在Windows系统对Nginx进行配置&#xff0c;并结合cpolar内网穿透工具实现固定公网地址远程访问多个本地站…

OpenMP和MPI环境配置

目录 OpenMP和MPI环境配置OpenMP环境配置MPI环境配置&#xff08;Windows&#xff09;MPI环境配置&#xff08;Ubuntu&#xff09; 参考资料 OpenMP和MPI环境配置 OpenMP环境配置 首先创建项目&#xff0c;选择C 控制台应用。 选择项目&#xff0c;属性。 在C/C —— 语言中&…

Raspbian安装云台

Raspbian安装云台 1. 源由2. 选型3. 组装4. 调试4.1 python3-print问题4.2 python函数入参类型错误4.3 缺少mjpg-streamer可执行文件4.4 缺失编译头文件和库4.5 python库缺失4.6 图像无法显示&#xff0c;但libcamera-jpeg测试正常4.7 异常IOCTL报错4.8 Git问题 5. 效果5.1 WEB…

目标检测 - RCNN系列模型

文章目录 1. RCNN2. Fast-RCNN3. Faster-RCNN 1. RCNN 论文&#xff1a;Rich feature hierarchies for accurate object detection and semantic segmentation 地址&#xff1a;https://arxiv.org/abs/1311.2524 分为两个阶段&#xff1a; 目标候选框Object ProposalsProposal…

Vmware安装Windows11虚拟机

Vmware安装Windows11虚拟机 文章目录 Vmware安装Windows11虚拟机效果一、准备工作①&#xff1a;下载镜像②&#xff1a;虚拟机 二、开始安装①&#xff1a;创建新的虚拟机②&#xff1a;自定义硬件③&#xff1a;编辑虚拟机设置④&#xff1a;开启虚拟机⑤&#xff1a;安装VMw…