当前位置:   article > 正文

数据结构(五)——树与二叉树的应用_数据结构-树和二叉树及其应用

数据结构-树和二叉树及其应用

5.5 树与二叉树的应用

5.5.1 哈夫曼树

结点的权:有某种现实含义的数值。

结点的带权路径长度:从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积。

树的带权路径长度:树中所有叶结点的带权路径长度之和(WPL,Weighted Path Length)


哈夫曼树的定义:在含有 n 个带权叶结点的二叉树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树,也称最优二叉树

哈夫曼树的构造
给定n个权值分别为w1, w2,..., wn的结点,构造哈夫曼树的算法描述如下:
1) 将这n个结点分别作为n棵仅含一个结点的二叉树,构成森林F.
2) 构造一个新结点,从F中选取两棵根结点权值最小的树作为新结点的左、右子树,并且将新结点的权值置为左、右子树上根结点的权值之和。
3) 从F中删除刚才选出的两棵树,同时将新得到的树加入F中。
4) 重复步骤2)和3),直至F中只剩下一棵树为止。


哈夫曼树的性质
1) 每个初始结点最终都成为叶结点,且权值越小的结点到根结点的路径长度越大。
2) 哈夫曼树的结点总数为 2n−1。
3) 哈夫曼树中不存在度为 1 的结点。
4) 哈夫曼树并不唯一,但 WPL 必然相同且为最优。

哈夫曼编码
固定长度编码――每个字符用相等长度的二进制位表示
可变长度编码――允许对不同字符用不等长的二进制位表示
若没有一个编码是另一个编码的前缀,则称这样的编码为前缀编码

有哈夫曼树得到哈夫曼编码――字符集中的每个字符作为一个叶子结点,各个字符出现的频度作为结点的权值,根据之前介绍的方法构造哈夫曼树

哈夫曼编码可用于数据压缩

5.5.2_1 并查集

逻辑结构:数据元素之间为“集合”关系

集合的两个基本操作——“并”和“查”
Find ——“查”操作:确定一个指定元 素所属集合
Union ——“并”操作:将两个不想交 的集合合并为一个

注:并查集(Disjoint Set)是逻辑结构——集合的一种具体实现,只进行 “并”和“查”两种基本操作
“并查集”的存储结构

“并查集”的代码实现——初始化

  1. #define SIZE 13
  2. int uFsets [ SIZE]; //集合元素数组
  3. //初始化并查集
  4. void Initial (int S[]){
  5. for(int i=0;i<SIZE;i++)
  6. s[i]=-1;
  7. }

“并查集”的代码实现——并、查

  1. //Find“查”操作,找x所属集合(返回x所属根结点)
  2. int Find (int S[],int x){
  3. while(S[x]>=0) //循环寻找x的根
  4. x=S[x] ;
  5. return x; //根的s[]小于0
  6. )
  7. // union“并”操作,将两个集合合并为一个
  8. void union(int S[],int Root1,int Root2){
  9. //要求Root1与Root2是不同的集合
  10. if(Root1==Root2)return;
  11. //将根Root2连接到另一根Root1下面
  12. S[Root2]=Root1;

Union操作的优化
优化思路:在每次Union操作构建树的时候,尽可能让树不长高
①用根节点的绝对值表示树的结点总数
②Union操作,让小树合并到大树

  1. // Union“并”操作,小树合并到大树
  2. void Union (int S[],int Root1,int Root2 ){
  3. if(Root1==Root2 ) return;
  4. if(S[Root2]>S[Root1]) { //Root2结点数更少
  5. S[Root1]+=S[Root2]; //累加结点总数
  6. S[Root2]=Root1; //小树合并到大树
  7. }else{
  8. S[Root2]+=S[Root1]; //累加结点总数
  9. S[Root1]=Root2; //小树合并到大树
  10. }
  11. }

 

5.5.2_2 并查集的进一步优化

拓展:Find操作的优化(压缩路径)
先找到根结点,再将查找路径上所有结点都挂到根结点下

  1. //Find“查"操作优化,先找到根节点,再进行“压缩路径”
  2. int Find(int S[],int x){
  3. int root = x;
  4. while(S[root]>=0) root=S[root]; //循环找到根
  5. while(x! =root){ //压缩路径
  6. int t=S[x]; //t指向x的父节点
  7. S[x]=root; //x直接挂到根节点下
  8. x=t;
  9. }
  10. return root; //返回根节点编号
  11. }



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/718399
推荐阅读
相关标签
  

闽ICP备14008679号