数据结构第五周笔记——树(下2)(慕课浙大版本--XiaoYu)

简介: 哈夫曼树的实现

5.2 哈夫曼树与哈夫曼编码

5.2.1 什么是哈夫曼树(Huffman Tree)

[例]将百分制的考试成绩转换成五分制的成绩

if(score<60 ) grade=1;

elseif(score<70) grade=2;

elseif(score<80) grade=3;

elseif(score<90) grade=4;

elsegrade=5;

上述代码中,其实对应着就有一棵树,如下图:

网络异常,图片无法展示
|

网络异常,图片无法展示
|

优化后的效率:

网络异常,图片无法展示
|

if(score<80)

{

   if(score<70 )

       if(score<60) grade=1;

   elsegrade=2;

}elseif(score<90 )grade=4;

elsegrade=5;

如何根据结点不同的查找频率构造更有效的搜索树?

哈夫曼树的定义

网络异常,图片无法展示
|

最优二叉树或哈夫曼树就是WPL最小的二叉树

一棵二叉树每一个叶结点的频率或者权重乘以这个叶结点到根结点的这个路径的长度就是带权路径的长度

权值 = 频率

[例]有五个叶子结点,它们的权值为{1,2,3,4,5},用此权值序列可以构造出形状不同的多个二叉树

网络异常,图片无法展示
|

网络异常,图片无法展示
|
是50

网络异常,图片无法展示
|

5.2.2 哈夫曼树的构造

  1. 每次把权值最小的两颗二叉树合并
  2. 网络异常,图片无法展示
    |

  3. 代码实现(如何选取两个最小的?)

typedefstructTreeNode*HuffmanTree;

structTreeNode{

   intWeight;

   HuffmanTreeLeft,Right;

}

HuffmanTreeHuffman(MinHeapH)

{

   //假设H->Size个权值已经存在H->Elements[]->Weight里

   inti; HuffmanTreeT;

   BuildMinHeap(H);//将H->Elements[]按权值调整为最小堆

   for(i=1;i<H->Size; i++){//做H->Size-1次合并

       T=malloc(sizeof(structTreeNode));//建立新结点

       T->Left=DeleteMin(H);//从最小堆中删除一个结点,作为新T的左子结点

       T->Right=DeleteMin(H);//从最小堆中删除一个结点,作为新T的右子结点

       T->Weight=T->Left->Weight+T->Right->Weight;//计算新权值

       Insert(H,T);//将新T插入最小堆

   }

   T=DeleteMin(H);

   returnT;

}

整体复杂度为O(NlogN)

  1. 哈夫曼树的特点:
  1. 没有度为1的结点;
  2. n个叶子结点的哈夫曼树共有2n-1个结点
  1. n0:叶结点总数
  2. n1:只有一个儿子的结点总数
  3. n2:有2个儿子的结点总数
  4. n2 = n0 - 1
  1. 哈夫曼树的任意非叶节点的左右子树交换后仍是哈夫曼树;
  2. 网络异常,图片无法展示
    |

5.2.3 哈夫曼编码

给定一段字符串,如何对字符进行编码,可以使得该字符串的编码存储空间最少?

网络异常,图片无法展示
|

分析:

  1. 用等长ASCII编码:58×8 = 464位
  2. 用等长3位编码:58×3 = 174位;
  3. 不等长编码:出现频率高的字符用的编码短些,出现频率低的字符则可以编码长些?

怎么进行不等长编码?

如何避免二义性(就是你这个编码不止一个意思)

  1. 前缀码prefix code:任何字符的编码都不是另一字符编码的前缀
  1. 可以无二义地解码(你的这个编码不能是其他编码的前缀)
  1. 二叉树用于编码:
  1. 左右分支:0、1
  2. 字符只在叶结点上
  3. 网络异常,图片无法展示
    |

  4. 网络异常,图片无法展示
    |

  5. 网络异常,图片无法展示
    |

  6. 怎么构造一颗编码代价最小的二叉树?
  1. 网络异常,图片无法展示
    |

小测验:哈夫曼树

网络异常,图片无法展示
|

5.3 集合及运算

5.3.1 集合的表示及查找

  1. 集合运算:交,并,补,差,判定一个元素是否属于某一集合
  2. 并查集:集合并、查某元素属于什么集合
  3. 并查集问题中集合存储如何实现?
  1. 可以用树结构表示集合,树的每个结点代表一个集合元素
  2. 网络异常,图片无法展示
    |
    对这样三棵树的存储方法
  1. 采用数组存储形式
  2. 网络异常,图片无法展示
    |

  3. 上图中没有父节点的用负数来表示,Parent是它父节点的下标

[例]:有10台电脑{1,2,3,.....,9,10},已知下列电脑之间已经实现了连接:

1和2、2和4、3和5、4和7、5和8、6和9、6和10

问:2和7之间,5和9之间是否是连通的?

2和7是连通的,5和9不连通

  1. 网络异常,图片无法展示
    |

集合运算

(1)查找某个元素所在的集合(用根结点表示)

intFind(SetTypeS[],ElementTypeX)

{

   //在数组S中查找值为X的元素所属的集合

   //MaxSize是全局变量,为数组S的最大长度

   inti;

   for(i=0;i<MaxSize&&S[i].Data!=X; i++);

   if(i>=MaxSize) return-1;//未找到X,返回-1

   for(;S[i].Parent>=0; i=S[i].Parent);//Parent的值为-1的时候就是找到根结点。i = S[i].Parent:原本指向i的位置现在跳到了s[i].Parent

   returni;//找到X所属集合,返回树根结点在数组S中的下标

}

5.3.2 集合的并运算

(2)集合的并运算

  1. 分别找到X1和X2两个元素所在集合树的根结点
  2. 如果它们不同根,则将其中一个根结点的父结点指针设置成另一个根结点的数组下标
  1. Union实现代码

voidUnion(SetTypeS[ ],ElementTypeX1,ElementTypeX2 )

{

   intRoot1,Root2;

   Root1=Find(S,X1);//得到X1与X2对应的树根

   Root2=Find(S,X2);

   if( Root1!=Root2 ) S[Root2].Parent=Root1;//判断如果不是本身就是同一个集合的,如果是同一个集合的话就不需要做这个并的操作。不同则合并

}

  1. 为了改善合并以后的查找性能,可以采用小的集合合并到相对大的集合中。(修改Union函数)。也许树的高度不会增加

小测验:集合

已知a、b两个元素均是所在集合的根结点,且分别位于数组分量3和2位置上,其parent值分别为-3,-2。问:将这两个集合按集合大小合并后,a和b的parent值分别是多少?

-5,3

集合的定义与并查

#define MAXN 1000                  /* 集合最大元素个数 */

typedefintElementType;           /* 默认元素可以用非负整数表示 */

typedefintSetName;               /* 默认用根结点的下标作为集合名称 */

typedefElementTypeSetType[MAXN]; /* 假设集合元素下标从0开始 */

voidUnion( SetTypeS, SetNameRoot1, SetNameRoot2 )

{ /* 这里默认Root1和Root2是不同集合的根结点 */

   /* 保证小集合并入大集合 */

   if ( S[Root2] <S[Root1] ) { /* 如果集合2比较大 */

       S[Root2] +=S[Root1];     /* 集合1并入集合2  */

       S[Root1] =Root2;

   }

   else {                         /* 如果集合1比较大 */

       S[Root1] +=S[Root2];     /* 集合2并入集合1  */

       S[Root2] =Root1;

   }

}

SetNameFind( SetTypeS, ElementTypeX )

{ /* 默认集合元素全部初始化为-1 */

   if ( S[X] <0 ) /* 找到集合的根 */

       returnX;

   else

       returnS[X] =Find( S, S[X] ); /* 路径压缩 */

目录
相关文章
|
11月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
269 0
|
7月前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
157 3
 算法系列之数据结构-Huffman树
|
7月前
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
510 19
|
9月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
194 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
9月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
185 12
|
9月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
166 10
|
9月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
261 3
|
11月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
284 5
|
11月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
395 16
|
11月前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
209 0