数据结构6树和二叉树_第1页
数据结构6树和二叉树_第2页
数据结构6树和二叉树_第3页
数据结构6树和二叉树_第4页
数据结构6树和二叉树_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 树形结构是一类非常重要的非线性数树形结构是一类非常重要的非线性数据结构,是以分支关系定义的层次结构。据结构,是以分支关系定义的层次结构。在计算机领域中有着广泛的应用。在计算机领域中有着广泛的应用。 本章重点讨论二叉树的存储结构及各本章重点讨论二叉树的存储结构及各种操作、树和森林与二叉树之间的转换关种操作、树和森林与二叉树之间的转换关系,最后给出一些应用实例。系,最后给出一些应用实例。 树树 是是n(n=0)个结点的有限集。个结点的有限集。 在任意一棵非空树中:在任意一棵非空树中: (1)有且仅有一个根结点;)有且仅有一个根结点; (2)除根结点外,其余的结点可分为)除根结点外,其余的结点可分

2、为m(m=0)个个互不相交的子树。互不相交的子树。ABCDEFGHIJKLM子树根结点ABCDEFGHIJKLM子树根结点二、术语二、术语结点:包含一个数据元素及若干指向其子树的分支结点:包含一个数据元素及若干指向其子树的分支结点的度:子树个数结点的度:子树个数树的度树的度: 树中最大的结点度数树中最大的结点度数叶子(叶子(K, L, F, G,M,I,J)分枝结点分枝结点 结点的层数、树的层数结点的层数、树的层数父结点、孩子结点父结点、孩子结点兄弟、堂兄弟兄弟、堂兄弟祖先、子孙祖先、子孙树的高度或深度树的高度或深度路径和路径长度路径和路径长度有序树与无序树有序树与无序树 森林是森林是m(m=

3、0)棵互不相交的树的集合)棵互不相交的树的集合。一、二叉树的定义一、二叉树的定义 或空,或由根和互不相交的左、右子树构成。或空,或由根和互不相交的左、右子树构成。二、基本形态二、基本形态abcdfgeacdg1 树与二叉树有什么区别树与二叉树有什么区别? 画出画出3个结点的树和个结点的树和3个结点的二叉树。个结点的二叉树。abcacd3个结点的二叉树个结点的二叉树:3个结点的树个结点的树abcacdacdacdacd1 树与二叉树有什么区别树与二叉树有什么区别? 画出画出3个结点的树和个结点的树和3个结点的二叉树。个结点的二叉树。2 度为度为2的树是二叉树吗的树是二叉树吗?反之呢?反之呢?3

4、n个结点的树的最大深度是多少个结点的树的最大深度是多少? 最小深度最小深度?4 n个结点的个结点的二叉树二叉树的最大深度是多少的最大深度是多少? 最小深度最小深度?性质性质1: 在二叉树的第在二叉树的第i (i0)层上至多有层上至多有2i-1个结点。个结点。性质性质2: 深度为深度为k的二叉树中至多有的二叉树中至多有2k-1个结点个结点(k0)。性质性质3: 对任何一棵二叉树对任何一棵二叉树T,如果其终端结点数为,如果其终端结点数为n0,度为度为2的结点数为的结点数为n2,则,则 n0=n2+1。性质性质3的证明:的证明: 证明证明: 设设n为二叉树中的结点总数,为二叉树中的结点总数,n1为二

5、叉树中度为为二叉树中度为1的结点个数。的结点个数。则有:则有: n=n0+n1+n2 (1) 考察二叉树的分支情况考察二叉树的分支情况: B=n-1 =2n2+n1 (2) 由由(2)得:得:n= 2n2+n1+1 (3) 由(由(1)和()和(3)得:)得:n0=n2+1 abcdgef 在二叉树的第在二叉树的第i 层上有层上有2i-1个结点个结点, 深度为深度为k的二叉树的二叉树有有2k-1个结点的二叉树。则此二叉树称为个结点的二叉树。则此二叉树称为“满二叉树满二叉树”。 如果一棵二叉树只有最下面的两层结点度数可以小如果一棵二叉树只有最下面的两层结点度数可以小于于2 2,并且最下面一层的结

6、点都集中在该层最左边的若,并且最下面一层的结点都集中在该层最左边的若干位置上,则此二叉树称为干位置上,则此二叉树称为“完全二叉树完全二叉树”。性质性质4: 有有n个结点的完全二叉树的深度个结点的完全二叉树的深度k为为: log2n +1。证明:假设深度为证明:假设深度为k,则根据性质,则根据性质2和完全二叉树的和完全二叉树的 定义有:定义有: 2k-1-1n = 2k-1 或或 2k-1 = n 2k 于是于是 k-1=log2n k 因因k是整数,是整数, 所以所以 k= log2n +1性质性质5: 如果对一棵有如果对一棵有n个结点的完全二叉树按层个结点的完全二叉树按层序从序从1开始编号,

7、则对任一结点开始编号,则对任一结点(i=i1, 则其双亲结点是则其双亲结点是 i/2 。(2)如果如果2i=n, 则结点则结点i的的左孩左孩 子是结点子是结点2i ;否则结点否则结点i无无 左孩子左孩子。(3)如果如果2i+1=n, 则结点则结点i的右的右 孩子是结点孩子是结点2i+1; 否则结否则结 点点i无右孩子无右孩子 。32个结点的完全二叉树,从根开始,按层次从左到个结点的完全二叉树,从根开始,按层次从左到右用右用1-32编号。编号。(1)它共有多少层?)它共有多少层?(2)各层最左边的结点的编号是多少?)各层最左边的结点的编号是多少?(3)编号为)编号为6的结点的左孩子的编号是多少?

8、的结点的左孩子的编号是多少? 它的右孩子呢?它的右孩子呢?(4)编号为)编号为16的结点的左孩子的编号是多少?的结点的左孩子的编号是多少? 它的右孩子呢?它的右孩子呢? (5)对于编号为)对于编号为8的结点,它的父结点的编号是多少?的结点,它的父结点的编号是多少? 编号为编号为13的结点呢?编号为的结点呢?编号为1的结点呢?的结点呢?6.2.3 二叉树的基本运算二叉树的基本运算 1. 1. 创建一棵空二叉树;创建一棵空二叉树;2. 2. 判断某棵二叉树是否为空;判断某棵二叉树是否为空;3. 3. 求二叉树中的根结点;求二叉树中的根结点;4. 4. 求二叉树中某个指定结点的父结点;求二叉树中某个

9、指定结点的父结点;5. 5. 求二叉树中某个指定结点的左子女结点;求二叉树中某个指定结点的左子女结点;6. 6. 求二叉树中某个指定结点的右子女结点;求二叉树中某个指定结点的右子女结点; 对于运算对于运算3636,当指定结点没有找到时,返回空。,当指定结点没有找到时,返回空。7. 7. 二叉树的遍历,即按某种方式访问二叉树中的所有二叉树的遍历,即按某种方式访问二叉树中的所有结点,并使每个结点恰好被访问一次。结点,并使每个结点恰好被访问一次。 6.2.4 二叉树的存储表示二叉树的存储表示1. 顺序表示顺序表示abcfhideg abcdfge 结论:结论:顺序结构适用于完全二叉树。顺序结构适用于

10、完全二叉树。思考:思考: 能否将一个顺序表视为一个完全二叉树呢?能否将一个顺序表视为一个完全二叉树呢? 基于顺序表的查找和排序能否在树表中进行呢?基于顺序表的查找和排序能否在树表中进行呢?struct btnodedatatypedata;struct btnode*lchild;struct btnode*rchild;typedef struct btnode btnode ;2.非顺序表示非顺序表示(1)二叉链二叉链ABCDEFG llink element rlink ABCDEFG2000000003456701234567struct sbtnode datatype data;

11、int llink, rlink; treen+1 ; /n:二叉树的结点个数二叉树的结点个数例例6-1 利用层次遍历方法建立二叉链表利用层次遍历方法建立二叉链表 以以三元组形式输入 (x,p,lr) , 其中 x:data , p: x的父结点, lr: x是p的左孩子(l)或是右孩子(r)。 首先输入 x, 建立根结点。同时让根结点入队。 然后,以以三元组形式输入(x,p,lr), 建立一个新结点,同时该结点入队。再找到p的地址,将x以左孩子或右孩子链入。 重复上述操作。 实现提示:利用实现提示:利用data成员作为队列。成员作为队列。int create_tree( ) int f,r;

12、 /f,r: 队尾和队首指针队尾和队首指针 scanf(x); tree1.data=x; tree1.llink=tree1.rlink=0; f=1;r=2; /建立根结点建立根结点,根结点入队根结点入队 for (r=2; rdata); /访问根结点访问根结点 Order(T-lchild); /先序遍历左子树先序遍历左子树 Order(T-rchild); /先序遍历右子树先序遍历右子树 T(n)=O(n) a b g d h i c f e abcdfge判断一个结点,判断一个结点,(1 1)不空)不空? ? 访问该结点访问该结点; ; 把它推入栈中把它推入栈中; ; 遍历它的左子

13、树遍历它的左子树. . (2)(2)空空? ? 栈顶结点出栈栈顶结点出栈; ; 找到这个结点的右子树,找到这个结点的右子树, 然后遍历它的右子树。然后遍历它的右子树。void preOrder(btnode *T) /先序遍历以先序遍历以T为根的二叉树为根的二叉树 initstack(s);/设置一个空栈设置一个空栈 while (T !=NULL |!empty(s) )if (T !=NULL) /若若T不空,则访问结点不空,则访问结点 Visite(T-data);/访问根结点访问根结点 push(s,T);/入栈入栈lchild;/沿左子树遍历沿左子树遍历 else pop(s,T);

14、 /栈顶元素出栈栈顶元素出栈 T=T-rchild; /沿右子树遍历沿右子树遍历 2、中序遍历、中序遍历void Order(btnode *T) /中序遍历以中序遍历以T为根的二叉树为根的二叉树 if (T) Order(T-lchild); /中序遍历左子树中序遍历左子树 Visite(T-data);/访问根结点访问根结点 Order(T-rchild);/中序遍历右子树中序遍历右子树 void inOrder(btnode * *T) /中序遍历以中序遍历以T为根的二叉树为根的二叉树 initstack(s);/设置一个空栈设置一个空栈 while (T|!empty(s) )if (

15、T) /若若T不空,则访问结点不空,则访问结点 push(s,T);lchild;/入栈,沿左子树遍历入栈,沿左子树遍历else pop(s,T); /栈顶结点栈顶结点T出栈出栈 visite(T-data);/访问根结点访问根结点 T=T-rchild;/遍历右子树遍历右子树 3、 后序遍历后序遍历void Order(btnode *T) /后序遍历以后序遍历以T为根的二叉树为根的二叉树 if (T) Order(T-lchild); /后序遍历左子树后序遍历左子树 Order(T-rchild);/后序遍历右子树后序遍历右子树 Visite(T-data);/访问根结点访问根结点 思考:

16、思考:后序遍历后序遍历非递归算法的设计非递归算法的设计?struct node datatype data; int llink, rlink; treen+1 ; /n:二叉树的结点个数二叉树的结点个数1、先序遍历先序遍历 void preorder( int p ) /前序遍历以前序遍历以p为根的二叉树为根的二叉树 if (p0) cout0) inorder(treep.llink); /中序遍历左子树中序遍历左子树 cout0) postorder(treep.llink); /后序遍历左子树后序遍历左子树 postorder(treep.rlink); /后序遍历右子树后序遍历右子树

17、 couttreep.data; /访问根结点访问根结点 void levelorder(int p) /层次遍历以层次遍历以p为根的二叉树为根的二叉树 四、层次遍历四、层次遍历int qn+1,r=1,f=1;/设置一个空队列设置一个空队列if (p!=0) qr+=p; / 根结点入队列根结点入队列while (f!=r) /当队列不空时当队列不空时 p=qf+; / 队首元素出队列队首元素出队列cout0) qr+=treep.llink; / 左子树入队左子树入队if (treep.rlink0) qr+=treep.rlink; / 右子树入队右子树入队思考思考1:出结果是什么?出结

18、果是什么?思考思考2:该算法的时间复杂性是多少?:该算法的时间复杂性是多少?结论:结论: 由二叉树性质由二叉树性质2可知,该算法的时间复杂性是可知,该算法的时间复杂性是 O(2n)例例6.5 算法算法1:void nodes(btnode *bt) / if (bt !=NULL) n+; / 计数计数 nodes(bt-lchild); / 求左子树的结点数求左子树的结点数 nodes(bt-rchild); / 求右子树的结点数求右子树的结点数 a b g d h i c f e 算法算法2:int nodes( btnode *bt) / if (bt =NULL) return 0;

19、/ 空的二叉树中结点个数为空的二叉树中结点个数为0 else return nodes(bt-lchild)+nodes(bt-rchild)+1; / 左子树上的结点数左子树上的结点数+右子树上的结点数右子树上的结点数+1(根)(根)abcdfeabcdfeint leafs(btnode *bt) / if (bt =NULL) return 0; / 空的二叉树,其叶子结点个数为空的二叉树,其叶子结点个数为0 else if (bt-lchild=NULL& bt-rchild=NULL) return 1; /叶子叶子 else return leafs(bt-lchild)+

20、leafs(bt-rchild); / 左子树上的叶子数左子树上的叶子数+右子树上的叶子数右子树上的叶子数abcdfe算法算法1:int depth(btnode *bt) / if (bt =NULL) return 0; / 空的二叉树深度为空的二叉树深度为0 else return 1+max(depth(bt-lchild), depth(bt-rchild)); / abcdfeint depth_2(btnode *bt) / high=level=0;/计二叉树的高度和层次计二叉树的高度和层次 t=bt; initstack(s); while (t!=NULL | ! empt

21、y(S) ) if (t!=NULL ) push(s,(t,+level); t=t-lchild; else (t,level)=pop(s); if (levelhigh ) high=level; t=t-rchild; return high;算法算法2:high=0level=0 ,2,2,3 ,3,4,4abcdfeint depth_3(btnode *bt) / initqueue(Q); enqueue(Q,(bt,1)); while ( ! empty(Q) (f,h)=delqueue(Q); if (f-lchild!=NULL) p=f-lchild; enquq

22、uq(Q,(p,h+1)); if (f-rchild!=NULL) p=f-rchild; enququq(Q,(p,h+1)); ; retuern(h);算法算法3:void exchang(btnode *bt) if (bt !=NULL) p=bt-lchild; bt-lchild=bt-rchild; bt-rchild=p; excheng(bt-lchild); excheng(bt-rchild); 思考:思考:采用后序遍历方法可以实现吗采用后序遍历方法可以实现吗? ?思考:思考:采用中序遍历方法呢采用中序遍历方法呢? ? 遍历二叉树是按一定的规则将二叉树中结遍历二叉树是

23、按一定的规则将二叉树中结点排列成一个线性序列;这实际上是把一个非点排列成一个线性序列;这实际上是把一个非线性结构进行线性化的操作。线性结构进行线性化的操作。6.3.2 线索二叉树线索二叉树 a b g d h i c f e 先序遍历序列先序遍历序列: abcdefghi中序遍历序列中序遍历序列: dcebfahgi后序遍历序列后序遍历序列: decfbhiga 层次遍历序列层次遍历序列: abgcfhide 若若ltag=0,lchildltag=0,lchild指向左子树,否则指向前趋结点;指向左子树,否则指向前趋结点;若若rtag=0,rchildrtag=0,rchild指向右子树,否

24、则指向后继结点;指向右子树,否则指向后继结点;struct ThrTreeNode / 线索二叉树中每个结点的结构线索二叉树中每个结点的结构 DataType data; ThrTreeNode *lchild,*rchild; int ltag, rtag; 利用结构中的空链域,并设立标志。利用结构中的空链域,并设立标志。以上结构构成的二叉链表作为二叉树的存储结构,叫做以上结构构成的二叉链表作为二叉树的存储结构,叫做 线索二叉链。线索二叉链。指向结点前驱或后继的指针叫做指向结点前驱或后继的指针叫做 线索线索。 加上线索的二叉树叫加上线索的二叉树叫 线索二叉树线索二叉树。对二叉树以某种次序遍历

25、使其变为线索二叉树的过程叫做对二叉树以某种次序遍历使其变为线索二叉树的过程叫做 。例:先序线索二叉树和先序线索二叉树链例:先序线索二叉树和先序线索二叉树链 (先序遍历序列:先序遍历序列:abcdfge)一、一、遍历线索二叉树遍历线索二叉树1、先序遍历、先序遍历 从根开始,找每个结点的后继结点。从根开始,找每个结点的后继结点。 void preOrder(struct ThrTreeNode *p p) /先序遍历以先序遍历以p为根的线索二叉树为根的线索二叉树 while (p!=NULL) visite(p-data); /访问根结点访问根结点 p=next(p); /按先序遍历顺序找按先序遍

26、历顺序找每个结点的后继结点每个结点的后继结点 if (p-ltag=0) p=p-lchildelse p=p-rchild 2、中序遍历、中序遍历(1)从根开始,沿着左子树找到一个无前驱的结点;)从根开始,沿着左子树找到一个无前驱的结点; (2)再找每个结点的后继结点。)再找每个结点的后继结点。 void inOrder(ThrTreeNode *p p) /中序遍历以中序遍历以p为根的线索二叉树为根的线索二叉树 while (p-ltag=0) p=p-lchild; / (1)从根开始,沿着左子树找到一个无前驱的结点)从根开始,沿着左子树找到一个无前驱的结点p; while (p!=NU

27、LL) visite(p-data); /访问根结点访问根结点 p=next(p); / 按中序遍历顺序找每个结点的后继结点按中序遍历顺序找每个结点的后继结点 思考:思考:中序遍历顺序找每个结点的后继结点中序遍历顺序找每个结点的后继结点?ThrTreeNode ThrTreeNode * *next(ThrTreeNodenext(ThrTreeNode * *p)p) /求求p p的后继结点的后继结点t t t=p-.rchild; t=p-.rchild; if (p-rtag=0) if (p-rtag=0) while (t-ltag=0) while (t-ltag=0) t=t-l

28、child; t=t-lchild; return(t); return(t); 3、后序遍历、后序遍历(1)从根开始,沿着左子树找到一个无前驱的结点;)从根开始,沿着左子树找到一个无前驱的结点; (2)再找每个结点的后继结点。)再找每个结点的后继结点。 void PostOrder(ThrTreeNode *p p) /后序遍历以后序遍历以p为根的线索二叉树为根的线索二叉树 while (p-ltag=0) p=p-lchild; / (1)从根开始,沿着左子树找到一个无前驱的结点)从根开始,沿着左子树找到一个无前驱的结点p; while (p!=NULL) visite(p-data);

29、/访问根结点访问根结点 p=next(p); / 按后序遍历顺序找每个结点的后继结点按后序遍历顺序找每个结点的后继结点 思考:思考:后序遍历顺序找每个结点的后继结点后序遍历顺序找每个结点的后继结点?二、二、静态线索二叉链静态线索二叉链 + + :左、右孩子;:左、右孩子; - - :前驱、后继线索:前驱、后继线索中序线索二叉树中序线索二叉树 中序(中序(静态)线索二叉链静态)线索二叉链中序遍历序列(中序遍历序列(bafdgce)bafdgce)6.4 树和森林树和森林 6.4.1 树和森林的定义树和森林的定义 树(树(Tree)是是n(n=0)个结点的有限集。个结点的有限集。 在任意一棵非空树

30、中:在任意一棵非空树中: (1)有且仅有一个根结点;有且仅有一个根结点; (2)除根结点外,其余结点可除根结点外,其余结点可分为分为m(m=0)个互不相交的子树。个互不相交的子树。 森林是森林是m(m=0)棵互不相交的树的集合。)棵互不相交的树的集合。OacgbdefOacgbdef3、孩子、孩子兄弟链兄弟链 (左孩子-右兄弟)OacgbdefOacgbdefOacgbdef (左孩子左孩子-右兄弟右兄弟)OacgbdefabOcgdefOacgbdef 先序遍历先序遍历: (1)访问根结点)访问根结点 (2)先序遍历每一个子树)先序遍历每一个子树 先序遍历序列先序遍历序列: o ab cdf

31、e gOacgbdefOacgbdef先序遍历序列:先序遍历序列: oabcdfegOacgbdef 后序遍历后序遍历: (1)后序遍历每一个子树)后序遍历每一个子树 (2)访问根结点)访问根结点 后序遍历序列:后序遍历序列: ba fdec g oOacgbdefOacgbdef后序遍历序列:后序遍历序列: bafdecgoOacgbdef先序遍历先序遍历-先序遍历先序遍历每一个树每一个树(abocdfeg)abOcgdefOacgbdef中序遍历中序遍历-后序遍历每一个树后序遍历每一个树(bafdecgo)abOcgdef(k1,k2),.,(k1,k2),.,ABCDEFG llink

32、element rlink ABCDEFG2000000003456701234567struct sbtnode datatype data; int llink, rlink; treen+1 ; /n:二叉树的结点个数:二叉树的结点个数6.6 huffman6.6 huffman树及应用树及应用6.6.1 6.6.1 二叉树的二叉树的带权路径长度带权路径长度 二叉树的带权路径长度:二叉树的带权路径长度: n WPL = wklk k=1其中,其中,n:n:叶子结点个数,叶子结点个数, w wk k : :第第k k个叶个叶子子的权,的权, l lk k : :第第k k个叶个叶子到根的路

33、径长度子到根的路径长度。 6.6.2 Huffman6.6.2 Huffman树树 对于有对于有n n个叶子,可以构造出多个二叉树。个叶子,可以构造出多个二叉树。 HuffmanHuffman树是一个带权路径长度最小的二叉树,树是一个带权路径长度最小的二叉树,又称又称最优二叉树最优二叉树。一、一、HuffmanHuffman树的构造方法树的构造方法 (1 1)将)将ww1 1,w,w2 2, ,.,w.,wn n 看成看成n n个二叉树;个二叉树; (2 2)选择)选择 2 2 个根结点的值最小的二叉树,个根结点的值最小的二叉树,构造构造1 1个新的二叉树;个新的二叉树;. .;直至剩;直至剩

34、1 1个树止。个树止。二、示例二、示例例例1:给定权值给定权值 7, 5, 2和和4,构造哈夫曼树。,构造哈夫曼树。1.75242462.3.115246524674.5.71152467115246186. 例:例:设包含设包含8个字符的字符集中各字符使个字符的字符集中各字符使用的相对频率分别为用的相对频率分别为 5,29,7,8,14,23,3,11, 试设试设计哈夫曼编码(教材第计哈夫曼编码(教材第146页例页例6-2)。)。1.以给定频率为权构造哈夫曼树;以给定频率为权构造哈夫曼树;514298731123 2.在哈夫曼树的所有左分支上编上号码在哈夫曼树的所有左分支上编上号码“0”,右

35、分支上编上号码右分支上编上号码“1”;873511231429 3.将根结点到将根结点到每个叶子结点的每个叶子结点的路径编码串起来路径编码串起来,得到字符集的哈得到字符集的哈夫曼编码。夫曼编码。111111100000001(5):0110 2(29):10 3(7):1110 4(8):11115(14):110 6(23):00 7(3):0111 8(11):010例3 某系统在通信联络中只可能出现8个字符,其 出现概率分别为 Z K F CUDLE 2 7 24 32374242120 构造 huffman 树。1 12 23 34 45 56 67 78 89 914235067we

36、ightllink rlink plink14000230007000600050000 0 0 0 0 三、存储结构三、存储结构 静态三叉链静态三叉链#define n 5#define n 5struct hnode struct hnode float weight; float weight; int llink; int llink; int rlink; int rlink; int plink; int plink;hnode huftree2hnode huftree2* *n;n;1 12 23 34 45 56 67 78 89 9(1)初值:)初值: 将将n个树叶看作个树

37、叶看作n个二叉树个二叉树在静态三叉链中构造在静态三叉链中构造huffman树树14235067weightllink rlink plink14000230007000600050000 0 0 0 0 1 12 23 34 45 56 67 78 89 9(2) 找两个根结点的值最小的二找两个根结点的值最小的二叉树叉树 6和和7 构造一个新的二叉树。构造一个新的二叉树。在静态三叉链中构造在静态三叉链中构造huffman树树1423506713weightllink rlink plink1400023000700660065000013430 0 0 0 slsr1 12 23 34 45

38、56 67 78 89 9(2) 找两个根结点的值找两个根结点的值最小的二叉树最小的二叉树 13 和和 14 构造一个新的二叉树。构造一个新的二叉树。在静态三叉链中构造在静态三叉链中构造huffman树树142350671327weightllink rlink plink140072300070066006500001343727610 0 0 slsr1 12 23 34 45 56 67 78 89 9(2) 找两个根结点的值最小的二找两个根结点的值最小的二叉树叉树 23 和和 27构造一个新的二构造一个新的二叉树。叉树。在静态三叉链中构造在静态三叉链中构造huffman树树142350

39、67132750weightllink rlink plink14007230087006600650000134372761850270 0 slsrweightllink rlink plink1400723008700660065000913437276185027958010014235067132750(2) 找两个根结点的值最小的二叉树找两个根结点的值最小的二叉树 50 和和 50构造一个新的二叉树。构造一个新的二叉树。100在静态三叉链中构造在静态三叉链中构造huffman树树1 12 23 34 45 56 67 78 89 9slsr四、算法设计四、算法设计 void set

40、_haffmantree() void set_haffmantree() for (i=1;illink= hti-rlink=0; /m=2*n-1 for (i=1;i=n;+i) hti.weight=wi; /初始化 for (i=n+1;i=m,+i) /建哈夫曼树 select(i-1,sl,sr); /在htk(1=k=i-1)中选择两个双亲域为零的最小的 / 结点 :sl和sr (sl和sr为最小值所在的下标) htsl.plink= htsr.plink=i; hti.llink=sl; hti.rlink=sr; hti.weight=htsl.weight + htsr

41、.weight ; Huffman编码是用于数据文件压缩的有效的编码编码是用于数据文件压缩的有效的编码方法。其压缩率通常在方法。其压缩率通常在20%90%之间。之间。Huffman编编码算法用字符在文件中出现的频率表来建立一个用码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。串表示各字符的最优表示方式。 6.6.3 哈夫曼编码哈夫曼编码 前缀编码前缀编码:对每一个字符规定一个对每一个字符规定一个0, 1串作为串作为其代码,并要求任一字符的代码都不是其它字符代其代码,并要求任一字符的代码都不是其它字符代码的前缀。码的前缀。 哈夫曼编码哈夫曼编码:依权值构造哈夫曼树依

42、权值构造哈夫曼树,根据此树得根据此树得到字符集的二进制前缀编码。到字符集的二进制前缀编码。 0左左,1右右一、前缀编码一、前缀编码&哈夫曼编码哈夫曼编码特点特点: 给出现频率高的字符较短的编码,出现频率给出现频率高的字符较短的编码,出现频率 较低的字符以较长的编码,可缩短总码长。较低的字符以较长的编码,可缩短总码长。二、二、前缀码与等长码的比较前缀码与等长码的比较weightllink rlink plink1400723008700660065000913437276185027958010014235067132750(2) 找两个根结点的值最小的二叉树找两个根结点的值最小的二叉树

43、 50 和和 50构造一个新的二叉树。构造一个新的二叉树。100在静态三叉链中构造在静态三叉链中构造huffman树树1 12 23 34 45 56 67 78 89 9111023008700660065000914235067132750100三、构造三、构造huffman码码hc1hc1Hc2Hc2hc3hc3hc4hc4hc5hc5100010 1 2 3 4 5 cd00001111 237650例如:abcabcddaabbadabda编码:010101011010001101001100译码:?问题:?为什么?思考:设通信用思考:设通信用4个字符个字符a,b,c,d, 分别出现

44、分别出现 7, 5, 2和和4次次 编码分别为:编码分别为:0,1,10,01 结果?结果?小结小结: : 树形结构的逻辑特点是,每个结点最多只有一个前驱,树形结构的逻辑特点是,每个结点最多只有一个前驱,但可以有多个后继,可以有多个终端结点。但可以有多个后继,可以有多个终端结点。 树和二叉树是两种典型的树形结构。在树中,每个结点树和二叉树是两种典型的树形结构。在树中,每个结点的度数不受限制。在二叉树中,每个结点的度数最多是的度数不受限制。在二叉树中,每个结点的度数最多是2,而且有有左子树和右子树之分。而且有有左子树和右子树之分。 满二叉树和完全二叉树是两种形态特殊的二叉树。高度满二叉树和完全二叉树是两种形态特殊的二叉树。高度为为h的满二叉树一定有的满二叉树一定有2h1个结点。高度为个结

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论