带权树存储
① 权值为2,3,4,5,6构成的哈夫曼树,带权路径长度为
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结手敏点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
(1)带权树存储扩展阅读:
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
若将树核薯斗中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
实现哈夫曼编码的方式主要是创建一个二叉树和其节点。这些树的节点可以存储在数组里,数组的大小为符号数的大小n,而节点分改磨别是终端节点(叶节点)与非终端节点(内部节点)。
② 什么是带权最优二元树
一毁运冲棵带权二元树的代价就是树中所有根结点权之和.代价最小的带权二元树称为最优二元树.问题转化为求最优带权二元树.
那么,什么是最优带权二元树呢?
最优二叉树,又称哈夫曼树,是一类带权路径长度最短的树,有着广泛的应用.
我们首先给出路径和路径长度的概念.从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目称做路径长度.树的路径长度是从树根到每一结点的路径长度之和.这种路径长度最短的二叉树是.
若将上述概念推广到一般情况,考虑带权的结点.结点的带权路径长度为从该结点树根之间的路径长度与结点上权的乘积.树的带权路径长度为树中所有叶子结点的带悄坦路径长度之和,通常记作
WPL=∑W(k)L(k) k=1...n
假设有n个权值W(1),W(2),.,W(n),试构造一棵有n个叶子结点的二叉树,每个叶子结点带权为W(k),则其中带权路径长度WPL最小的二叉树称做最优二又树或哈纤歼夫显树.
③ 求带权4,5,7,10,11,12,15的最优二叉树并计算它的权
带权二叉树是指一种用来表示带权信息的二叉树,常用于数据压缩和信息编码。
建立带权二叉树的一种方法是采用贪心算法,具体流程如下:
将所有的带权信息按权值从小到大排序。纤敬
取出权值最小兄竖敏的两个信息,将它们合并成一个新的信息,新信息的权值为两个信息的权值之和。
将新信息加入羡枝到剩余的信息中,继续执行步骤2直到所有的信息都合并为一个。
合并出的最后一个信息即为带权二叉树的根节点。
根据上述流程,我们可以建立带权4,5,7,10,11,12,15的最优二叉树。首先将所有的信息按权值从小到大排序得到4,5,7,10,11,12,15。然后依次合并,得到如下的二叉树:
Copy code
11
/
4 7
/
5 10
/
12 15
该二叉树的权值为11+4+7+5+10+12+15=64。
注意:这里只是一种建立带权二叉树的方法,并不一定是最优解。
④ 带权路径长度是什么
带权路径长度也就是树的带权路径长度,树的路径长度是从树根到树中每一结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径粗兄吵长度最短。
结点的权:在一些应用中,赋予树中结点的尘衡一个有某种意义的实数。
结点的带权路径长度:结点到树根之间的路径长度与该结点上权的乘积。
特性:
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径岩侍长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
实现哈夫曼编码的方式主要是创建一个二叉树和其节点。这些树的节点可以存储在数组里,数组的大小为符号数的大小n,而节点分别是终端节点(叶节点)与非终端节点(内部节点)。
⑤ 初步认识哈夫曼树
7.哈夫曼数的基本概念:
(1)路径:模带由一结点到另一结或码派点间的分支所构成
(2)路径长度:路径上的分支数目a→d的路径长度= 2
(3)树的路径长度:从树根到每一结点的路径长度之和。 例图:10
(4)权:赋予某个实体的一个量,是对实体的属性的数值化描述。若树的结点带有权值,即为带权树。
(5)结点的带权路径长度:结点到根的路径长度与结点上权值的乘积d的带权路径长度=7*2=14
(6)树的带权路径长度:树中所有叶子结点的带权路径长度之和。例图:2*7+2*5+2*2+2*4=36
(7)赫夫曼树(Huffman):最优二叉树,带权路径长度最小的树
哈夫曼树的特点
–权值大的结点到根结点的路径长度短;
–权值小的结点到根结点的路径长度长。
Ø哈夫曼编码树中没有度为1的结点;
Ø若给定n个权值(n个叶子结点),则哈夫曼树的总结点数为 2n-1;
Ø哈夫曼树的高度不超过n。
哈夫曼数的构造算法:
哈夫曼编码:
v前缀编码:任一字符的编码都不是另一字符编码的前缀。
如:字符a、b、c、d的编码分别为0、1、01、10,则a的编码是c的编码的前缀,b的编码是d编码的前缀,该编码不是前缀编码。
在译码时,对于01011011的译码结果将不唯一。
v哈夫曼编码
对一棵具有n个叶子的哈夫曼树,对每个左分支赋予0,右分支赋予1,则从根到每个叶子的路径上,分别构成一个二进制串,该二进制串称为哈夫曼编码。
进行哈夫曼编码,先建哈夫曼树。
哈夫曼编码是前缀编码,且是最优前缀编码衫贺。
⑥ 最优二叉树
最优二叉树概念
.树的路径长度 树的路径长度是从树根到树中每一结点的路径长度之和 在结点数目相同的二叉树中 完全二叉树的路径长度最短
.树的带权路径长度(Weighted Path Length of Tree 简记为WPL) 结点的权 在一些应用中 赋予树中结点的一个有某种意义的实数 结点的带权路径长度 结点到树根之间的路径长度与该结点上权的乘积 树的带权路径长度(Weighted Path Length of Tree) 定义为树中所有叶结点的带权路径长度之和 通常记为 其中 n表示叶子结点的数目w i和l i分别表示叶结点k i的权值和根到结点ki之间的路径长度 树的带权路径长度亦称为树的代价
.最优二叉树或哈夫曼树 在权为wl w … wn的n个叶子所乎困构成的所有二叉树中 带权路径长度最小(即代价最小)的二叉树称为最优二叉树或哈夫曼树 【例】给定 个叶子结点a b c和d 分别带权 和 构造如下图所示的三棵二叉树(还有许多棵) 它们的带权路径长度分别为 (a)WPL= * + * + * + * = (b)WPL= * + * + * + * = (c)WPL= * + * + * + * = 其中(c)树的WPL最小 可以验证 它就是哈夫曼树
注意 ① 叶子上的权值均相同时 完全二叉树一定是最优二叉树 否则完全二叉树不一定是最优二叉树 ② 最优二叉树中 权越大的叶子离根越近 ③ 最优二叉树的形态不唯一 WPL最小
构造最优二叉树
.哈夫曼算法 哈夫曼首先给出了对于给定的叶子数目及其权值构造最优二叉树的方法 故称其为哈夫曼算法 其基本思想是 ( )根据给定的n个权值w l w … wn构成n棵二叉树的森林F={T T … T n} 其中每棵二叉树T i中都只有一个权值为w i的根结点 其左右子树均空 ( )在森林F中选出两棵根结点权值最小的树(当这样的树不止两棵树时 可以从中任选两棵) 将这两棵树合并成一棵新树 为了保证新树仍是二叉树 需要增加一个新结点作为新树的根 并将所选的两棵树的根分别作为新根的左右孩子(谁左 谁右无关紧要) 将这两个孩子的权值之和作为新树根的权值 ( )对新的森林F重复( ) 直到森林F中只剩下一棵树为止 这棵树便是哈夫曼树 用哈夫曼算法构造哈夫曼树的过程见【动画演示】 注意 ① 初始森林中的n棵二叉树 每棵树有一个孤立的结点 它们既是根 又是叶子② n个叶子的哈夫曼树要经过n 次合并 产生n 个新结点 最终求得的哈夫曼树 *** 有 n 个结点 ③ 哈夫曼树是严格的二叉树 没有度数为 的分支结点 .哈夫曼树的存储结构及哈夫曼算法的实现 ( ) 哈夫曼树的存储结构 用一个大小为 n 的向量来存储哈夫曼树中的结点 其存储结构为 #define n //叶子数目 #define m *n //树中结点总数 typedef struct { //结点类型 float weight //权值 不妨设权值均大于零 int lchild rchild parent //左右孩岁橡念子及双亲指针 }HTNode typedef HTNode HuffmanTree[m] //HuffmanTree是向量类型 注意 因为C语言数组的下界为 故用 表示空指针 树中某结点的lchild rchild和parent不等于 时 它们分别是该结点的左 右孩子和双亲结点在向量中的下标 这里设置parent域有两个作用 其一是使查找某结点的双亲变得简单 其二是可通过判定parent的值是否为 来区分根与非根结点
( )哈夫曼算法的简要描述 在上述存储结构上实现的哈夫曼算法可如迹大致描述为(设T的类型为HuffmanTree) ( )初始化 将T[ ..m ]中 n 个结点里的三个指针均置为空(即置为 ) 权值置为 ( )输人 读人n个叶子的权值存于向量的前n个分量(即T[ ..n ])中 它们是初始森林中n个孤立的根结点上的权值 ( )合并 对森林中的树共进行n 次合并 所产生的新结点依次放人向量T的第i个分量中(n≤i≤m ) 每次合并分两步 ①在当前森林T[ ..i ]的所有结点中 选取权最小和次小的两个根结点[p ]和T[p ]作为合并对象 这里 ≤p p ≤i ② 将根为T[p ]和T[p ]的两棵树作为左右子树合并为一棵新的树 新树的根是新结点T[i] 具体操作 将T[p ]和T[p ]的parent置为i 将T[i]的lchild和rchild分别置为p 和p 新结点T[i]的权值置为T[p ]和T[p ]的权值之和 注意 合并后T[pl]和T[p ]在当前森林中已不再是根 因为它们的双亲指针均已指向了T[i] 所以下一次合并时不会被选中为合并对象 哈夫曼算法模拟演示过程【参见动画模拟】
( )哈夫曼算法的求精 void CreateHuffmanTree(HuffmanTree T) {//构造哈夫曼树 T[m ]为其根结点 int i p p InitHuffmanTree(T) //将T初始化 InputWeight(T) //输入叶子权值至T[ ..n ]的weight域 for(i=n i<m i++){//共进行n 次合并 新结点依次存于T[i]中 SelectMin(T i &p &p ) //在T[ ..i ]中选择两个权最小的根结点 其序号分别为p 和p T[p ] parent=T[p ] parent=i TIi] child=p //最小权的根结点是新结点的左孩子 T[j] rchild=p //次小权的根结点是新结点的右孩子 T[i] weight=T[p ] weight+T[p ] weight } // end for }上述算法中调用的三个函数【参见练习】 【例】以 个权值 为例 执行CreateHuffmanTree求最优二叉树的过程【参见动画模拟】
lishixin/Article/program/sjjg/201311/23014
⑦ 数据结构怎么用以存储边(带权)的一维数组表示图。
一般在数据山纳结构里面,指针比较吃香。但是,也会用到一维数组和二维数组:比如说,线性表或者链表的遍历,插入元素,删除元素……而要用到二维数组的就是在需要邻逗清没接矩阵的时候啦。
一般来说,程序里,有这样一种声明一维数组和二维数组的方法:
typedef struct
{
int *elem;
……
}; //以后就可以用elem[i];(i=0,1,2,…,length) 这就是一维数组啦
typedef struct
{
…正简…
}matrix[row][column]; //这就是二维数组啦