数据结构学习笔记-森林和二叉树的转化、最优二叉树

来源:互联网 发布:淘宝怎样看自己几颗心 编辑:程序博客网 时间:2024/06/08 03:14

森林和二叉树的转化

孩子兄弟表示法:

任何一棵和树对应的二叉树,其右子树必为空。森林中将第二棵树的兄弟,则可得到森林和二叉树的对应关系。

最优二叉树(赫夫曼树)

赫夫曼树:又称最优树,是一类带权路径长度最短的树。

树的路径长度:从树根到每一结点的路径长度(从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称作:路径长度)之

树的带权路径长度:树中所有叶子结点权路径长度(从该叶子结点到根之间的路径长度与结点上权的乘积)之和,通常记作:

假设有n个权值{w1,w2,...,wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wi,则其中带权路径长度WPL最小的二叉树称做最优二叉树

赫夫曼算法:这篇文章中说的很详细链接

赫夫曼编码:也就是通过赫夫曼树产生的非定长前缀码(任何一个编码都不是另一个编码的前缀,这种编码叫前缀编码),其中每种字符在电文中出现的次数为wi,编码长度为Li,电文总长度为w1*L1+w2*L2+...+wn*Ln。

赫夫曼编码实现

赫夫曼树中没有度为1的结点(称为正则二叉树)则一棵有n个叶子结点的赫夫曼树共有2n-1个结点,因此可以存储在一个大小为2n-1的一维数组中。由于在构成赫夫曼树之后,为求编码需要从叶子结点出发走一条从叶子到根的路径(这里说的从叶子到根指的是在程序中进行赫夫曼编码时,是从parent域非零到parent域为零这个过程);而为译码需要从根出发走一条从根到叶子的路径。

赫夫曼编码的产生方式有两种,第一种是:从叶子到根逆向求每个字符的赫夫曼编码;第二种是:从根出发,遍历整棵赫夫曼树。不过不管是使用哪种方式来生成编码其赫夫曼树的存储方式都没有改变。

不过这里采用的方法与上面链接中所描述的方法略有不同。这里不对叶子结点按其权值进行排序,举个例子有8种字符,其概率分别是0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11。可以设权w={5,29,7,8,14,23,3,11}其编码过程如下图所示:

 

结点中的数字表示该结点的权值,至于哪个结点为左孩子,哪个结点为右孩子要看其在数组中的存储位置(即下标),下标小的作为左孩子,另外一个作为右孩子。

下面首先,给出程序中需要用到的结构体,定义的宏,函数声明

其次,赫夫曼编码的代码,及两个用到的子函数

{需要注意代码中的s1和s2指的是结点下标;HC的类型是二级指针,其可以用来表示指针数组的首地址;HT分配的空间时2n也就是说HT[0]不使用,HC分配的空间为n+1,HC[0]也不使用;根结点的标志是其parent域为0;上面代码所使用的编码产生方法是从叶子结点到根结点,逆序存储编码到工作空间,然后将编码从工作空间复制到编码空间。

另外一种编码方式,是从根结点出发遍历整棵赫夫曼树

 

0 0
原创粉丝点击