8. 二叉树和哈夫曼树-数据结构入门(c语言实现)

目录

二叉树

二叉树的定义

二叉树的特点

二叉树的五种基本形态:

二叉树与度为2的有序树的区别:

特殊的二叉树

二叉树的性质

二叉树-存储结构

遍历二叉树

根据遍历序列确定二叉树

树的存储结构

哈夫曼树

哈夫曼树的构造

哈夫曼编码


二叉树

二叉树结构简单,存储效率较高,运算的算法也相对简单。树或森林与二叉树之间可以相互转换。正与负、真与假、对与错等都适合用二叉树结构来建模。

二叉树的定义

二叉树(Binary Tree)是n(n≥0)个节点的有限集合。

这个集合或者为空(n=0),称为空二叉树。

或者由一个根节点和两棵互不相交的称为左子树和右子树的二叉树组成。

二叉树的特点

每个节点最多有两棵子树,二叉树中不存在度大于2的节点。

左、右子树的次序不能任意颠倒。

二叉树的结构最简单,规律性最强;

可以证明,所有树都能转为唯一对应的二叉树,不失一般性。

二叉树的五种基本形态:

8. 二叉树和哈夫曼树-数据结构入门(c语言实现)_第1张图片

二叉树可以采用树的逻辑结构表示法,4种表示法有:

1.树形表示法;   

2.文氏图表示法;

3.凹入表示法;   

4.括号表示法;

二叉树与度为2的有序树的区别:

1、二叉树的度不一定是2

2、某一结点只有一个孩子时,有序树无左右之分,而二叉树仍有左右之分

特殊的二叉树

满二叉树

所有分支节点都有双分节点,并且叶节点都集中在二叉树的最下一层。

8. 二叉树和哈夫曼树-数据结构入门(c语言实现)_第2张图片

在一棵满二叉树中:高度为h的二叉树恰好有2h-1个节点。

完全二叉树

最多只有下面两层的节点的度数小于2;并且最下面一层的叶节点都依次排列在该层最左边的位置上。

8. 二叉树和哈夫曼树-数据结构入门(c语言实现)_第3张图片

完全二叉树实际上是对应的满二叉树删除叶节点层最右边若干个节点得到的。

二叉树的性质

性质1

对于任何一棵二叉树,若2度的结点数有n2个,则叶子数n0必定为n2+1 (即n0=n2+1)。

性质2

非空二叉树上第i层上至多有2i-1个节点(i>=1)。

性质3

高度为h的二叉树至多有2h-1个节点(h>=1)。

完全二叉树性质(含n个节点)

1.n1=0或者n1=1。n1可由n的奇偶性确定,n为奇数,n1=0,n为偶数,n1=1

2.若i≤ (n/2下取整) ,则编号为i的节点是分支节点,否则为叶子节点。

3. 除树根节点外,若一个节点的编号为i,则它的双亲节点的编号为⌊i/2⌋(下取整)。

4. 若编号为i的节点有左孩子节点,则左孩子节点的编号为2i;

若编号为i的节点有右孩子节点,则右孩子节点的编号为2i+1。

二叉树-存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。

顺序存储

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

对于完全二叉树,只要从根起按层序存储即可,依次自上而下、自左至右存储结点元素,即 将完全二叉树上编号为i 的结点元素存储在如 上定义的一维数组中下标为i-1的分量中。

在最坏的情况下,一个深度为K 且只有K个结点的单支树(树中不存在度为2 的结点)却需要长度为2^k -1的一维数组。这造成了存储空间的极大浪费, 所以对于一般二叉树,更适合采取下面的链式存储结构。

链式存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。链式结构又分为二叉链和三叉链,目前学习大部分用二叉链。

二叉链的结构:

8. 二叉树和哈夫曼树-数据结构入门(c语言实现)_第4张图片

三叉链多一个指向双亲的指针域。

遍历二叉树

遍历二叉树(traversing binary tree)是指按某条搜索路径巡访树中每个结点,使得每个结点 均被访问一次,而且仅被访问一次。遍历二叉树是二叉树最基本的操作,也是二叉树其他各种操作的基础,遍历的实质是对二叉树进行线性化的过程,即遍历的结果是将非线性结构的树中结点排成一个线性序列。

平时主要使用的有四种遍历方法:先序遍历、中序遍历、后续遍历,层序遍历。

先序遍历二叉树: 若二叉树为空,则空操作;

若不为空:

(1)访问根结点;

(2)先序遍历左子树;

(3)先序遍历右子树。

中序遍历二叉树: 若二叉树为空,则空操作;

若不为空:

(1)中序遍历左子树;

(2)访问根结点;

(3)中序遍历右子树。

后序遍历二叉树: 若二叉树为空,则空操作;

若不为空:

(1)后序遍历左子树;

(2)后序遍历右子树;

(3)访问根结点。

层序遍历:

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的 根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然 后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

根据遍历序列确定二叉树

由二叉树的先序序列和中序序列,或由 其后序序列和中序序列均能唯一地确定一棵二叉树。

自己研究。

树的存储结构

  1. 双亲表示法

这种表示方法中,以一组连续的存储单元存储树的结点,每个结点除了数据域data外,还附 设一个parent域用以指示其双亲结点的位置。

  1. 孩子表示法

由于树中每个结点可能有多棵子树,则可用多重链表,即每个结点有多个指针域, 其中每个 指针指向一棵子树的根结点。

  1. 孩子兄弟法

又称二叉树表示法,或二叉链表表示法,即以二叉链表做树的存储结构。链表中结点的两个 链域分别指向该结点的第一个孩子结点和下一个兄弟结点。

哈夫曼树

  哈夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树。

路径:

从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。

路径长度:

路径上的分支数目称作路径长度。

树的路径长度:

从树根到每一结点的路径长度之和。

权:

从树根到每一结点的路径长度之和。

结点的带权路径长度:

从该结点到树根之间的路径长度与结点上权的乘积。

树的带权路径长度:

树中所有叶子结点的带权路径长度之和,通常记作

8. 二叉树和哈夫曼树-数据结构入门(c语言实现)_第5张图片

 

哈夫曼树:

假设有m个权值{w1, W2, …,Wm},可以构造一棵含n个叶子结点的二叉树, 每个叶子结点的权为Wi, 则其中带权路径长度 WPL最小的二叉树称做最优二叉树或哈夫曼树。

n为叶子结点个数

wk为第k个叶子结点的权值

lk为第k个叶子结点的路径长度

 

哈夫曼树的构造

1. 哈夫曼树的构造过程

(1)由给定的n个权值{W1,W2,…,Wn}对应的n个结点构成n棵二叉树的森林:F={T1,T2,…,Tn},其中,每棵二叉树Ti只有一个权为Wi的根结点,其左右子树为空;

(2)在F中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和;

(3)在集合F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到集合F中;

(4)重复(2)、(3)两步,当F中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。

哈夫曼编码

      在数据通讯中,经常需要将传送的文字转换成由二进制字符0,1组成的二进制代码,称之为编码。

      如果在编码时考虑字符出现的频率,让出现频率高的字符采用尽可能短的编码,出现频率低的字符采用稍长的编码,构造一种不等长编码,则电文的代码就可能更短。

      哈夫曼编码是一种用于构造使电文的编码总长最短的编码方案。

求哈夫曼编码的方法

1.先构造哈夫曼树;

2.在哈夫曼树上求叶结点的编码;

规定哈夫曼树中的左分支代表0,右分支代表1,则从根结点到每个叶结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码。

在一组字符的哈夫曼编码中,不可能出现一个字符的哈夫曼编码是另一个字符哈夫曼编码的前缀。

哈夫曼树中没有度为1的结点。

你可能感兴趣的:(数据结构入门(C语言),数据结构,c语言,算法)