数据结构与算法 复习笔记 第五章二叉树 概念/二叉树的周游/二叉树的存储/二叉搜索树/Huffman树及其应用

5.1二叉树的概念

5.1.1二叉树的定义和基本术语

二叉树的结点有左右之分,不能颠倒。
二叉树的结点与表的元素类似,可以表示任何一种数据类型。
二叉树中一个结点的子树数目称为该结点的度(degree),叶节点的度为零。
除叶结点以外那些非终端结点称为内部节点(或分支结点,internal node)。
父节点k与子节点k’之间存在一条有向连线<k,k’>,称作边(edge)。

5.1.2满二叉树、完全二叉树、扩充二叉树

满二叉树和完全二叉树是两种特殊形态的二叉树。
如果一棵二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree)。
如果一棵二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree)。
完全二叉树的特点是其吐结点只可能在层次最大的两层出现。完全二叉树中由根结点到各个结点的路径长度总和在具有同样结点个数的二叉树中达到了最小,即任意一棵二叉树中根结点到各结点的最长路径一定不短于结点数目相同的完全二叉树中的路径长度。
扩充二叉树是满二叉树,新增空树叶(外部结点)的个数等于原二叉树的结点(内部结点)个数加1.

5.1.3二叉树的主要性质

性质1、在二叉树中,第i层上最多有2^i个结点(i>=0)。
性质2、深度为k的二叉树至多有2^(k+1)-1个结点(k>=0)。
性质3、任何一颗二叉树,若其终端节点数为n0,度为2的节点数为n2,则n0=n2+1 。
性质4、满二叉树定理:非空满二叉树树叶数目等于其分支结点数加1 。
性质5、满二叉树定理推论:一个非空二叉树的空子树数目等于其节点数加1 。
性质6、有n个结点(n>0)的完全二叉树的高度为[log2(n+1)](取上限),深度为[log2(n+1)]-1 。
性质7、对于具有n个结点的完全二叉树,结点按层次从左到右编号,则对任意结点i(o<=i<=n-1)有:
(1)如果i=0,则结点i是二叉树的根结点;若i>0,则其父结点编号是L(i-1)/2」。
(2)当2i+1≤n-1时,结点i的左子结点是2i+1,否则结点i没有左子结点。
当2i+2<n-1时,结点i的右子结点是2i+2,否则结点i没有右子结点。
(3)当i为偶数且0<i<n时,结点i的左兄弟是结点i-1,否则结点i没有左兄弟。
当i为奇数且i+1<n时,结点i的右兄弟是结点i+1,否则结点i没有右兄弟。

5.2二叉树周游

5.2.1二叉树的抽象数据类型

template
class BinaryTreeNode {
friend class BinaryTree; //声明二叉树类为结点类的友元类,以便访问私有数据成员
private:
T info; //二叉树结点数据域
public:
BinaryTreeNode(); // 默认构造函数
BinaryTreeNode(const T& ele); //给定数据的构造函数
BinaryTreeNode(const T& ele, BinaryTreeNode I, BinaryTreeNode* r);
//子树构造结点
T value()const; //返回当前结点的数据
BinaryTreeNode < T >* leftchild()const; //返回当前结点的左子树
BinaryTreeNode < T >* rightchild()const; //返回当前结点的右子树
void setLeftchild(BinaryTreeNode ); // 设置当前结点的左子树
void seiRightchild(BinaryTreeNode < T >
); // 设置当前结点的右子树
void setValue(const T& val); / / 设置当前结点的数据城
bool isLeaf()const; //判断当前结点是否为叶结点
BinaryTreeNode & operator =(const BinaryTreeNode & Node); //重载赋值操作符
}
//【代码 5.1 结束】
//【代码5.2】 二叉树的抽象数据类型。
template
class BinaryTree {
private:
BinaryTreeNode * root; // 二叉树根结点
public:
BinaryTree() | root = NULL;; // 构造函数
-BinaryTree(()[DeleleBinaryTree(root);; // 析构函数
bool isEmpty()const; //判定二叉树是否为空树
BinaryTreeNode * Root()[return root;l; //返回二叉树根结点
BinaryTreeNode * Parent(BinaryTreeNode* current); //返回当前结点的父结点
BinaryTreeNode * LeftSibling(BinaryTreeNode * current);
}

所谓二叉树的周游(或称遍历,raversal)是指按照一定顺序依次访问树中所有的结点,并便得每个结点仅被访问一次。这里所说的“访问”是指操作,可以理解成对二叉树结点数据成员的处理,例如输出、修改结点的信息等。

5.2.2深度优先周游二叉树
点击链接

基于二叉树的递归定义,这3种深度优先周游的递归定义如下:
(1)前序法(ILR次序,preonder traversal)。其递归定义是:
*
访问根结点。
*
按前序周游左子树。
*
按前序周游右子树。

(2)中序法(LaR次序,inordertraversal)。其递归定义是:
*
按中序周游左子树。
*
访问根结点。
*
按中序周游右子树。

(3)后序法(LRt次序,postordertraversal)。其递归定义是:
*
按后序周游左子树。
*
按后序周游右子树。
*
访问根结点。

5.3二叉树的存储结构

点击链接
二叉树的存储结构可以分为顺序存储结构和链式存储结构。
二叉树的顺序存储结构:
就是将二叉树中各个节点的值按照一定的顺序存放在一组地址连续的存储单元中。
由于二叉树本身是非线性结构,所以首先要对二叉树中的节点进行排序,从而确定各个节点的逻辑关系。例如可以从根节点开始自上而下按层进行编号,如图所示:

按照节点的排序规则决定了节点在存储单元中的相对位置,而且我们发现这种存储结构非常适合存储完全二叉树,在这种情况下,存储空间的利用率也是最高的。对于非完全二叉树,可以补全为完全二叉树,在进行顺序存储的时候只需要将补进入的节点置空(不放任何值),但是这就带来了存储空间利用率低下的问题。
二叉树的链式存储结构:
二叉式的链式存储就是将二叉树中的各个节点随机的存放在位置任意的内容空间中,各个节点之间的逻辑关系通过指针来反应。(这种随机只是指存储地址的相对随机性,就是存储地址可以不连续)。链式存储结构又可以分为二叉链表结构和三叉链表结构。其中二叉链表结构中,每个节点设置有三个域:数据域、左孩子域和右孩子域,数据域用来存储节点的值,左右孩子域存储的是其左右孩子节点的存储地址(其实就是两个指针)。三叉链表结构在二叉链表结构上增加了一个父节点域用于存放该节点的父节点的存储地址,具体结构示意图如下:

相比二叉链表结构,三叉链表结构增加了一个父节点指针带来的好处是便于查找双亲节点,但是也增加了存储空间的开销。在实际应用中常常用二叉链表结构用于表示二叉树。
无论是二叉树的二叉链式还是三叉链式存储结构又可以分为带头结点的和不带头节点的。
在含有n个结点的二叉链表中有n+1个空链域。

5.4二叉搜索树

点击链接

5.5堆与优先队列

点击链接

5.6Huffman树及其应用(有空填坑)

点击链接

本章小结

本章介绍了二叉树的概念。与线性表、栈、队列一样,二叉树也是一种重要的数据结构,而且应用十分广泛。
在二叉树中,每个结点最多有两个子结点。由二叉树的逻辑结构给出了二叉树的递归定义:
二叉树若不为空,则由根结点和两棵互不相交的子树构成,其左右子树也是二叉树。随后给出了几种特殊的二叉树结构,例如满二叉树、完全二叉树和扩充二叉树。
二叉树周游是指按照一定顺序依次访问树中的所有结点,且使得每一个结点仅被访问一次。
根据访问结点和左右子树的次序不同,二叉树的周游算法可以分为深度优先周游和广度优先周游。深度优先周游算法有前序、中序和后序3种。在此给出了二叉树深度优先周游的递归和非递归实现。
二叉树的抽象数据类型的各个成员函数的实现需要参考具体的存储结构和应用。二叉树有两种主要的实现方式:链式存储结构和顺序存储结构。用指针实现二叉树是常用的方法,其中每个结点包含数据域和左、右指针域,分别用来存储结点本身的信息和指向左、右子结点的指针。
这种存储方式称为二叉链表。顺序存储方式主要介绍了用数组实现完全二叉树,即一棵具有n个结点的完全二叉树按层次顺序把所有结点从0到n-1编号,按编号的次序将所有结点元素存储在一维数组中。
二叉搜索树(BST)是一种重要的索引结构,可以用于快速检索。BST 每个结点关键码的值大于其左子树上所有结点的关键码值,而小于其右子树上所有结点的值,且其左右子树分别为一棵二叉搜索树。因此,按中序周游二叉搜索树可以得到关键码的正序序列。在二叉搜索树中进行检索可以得到较高的效率,动态插入和删除结点时需要保持二叉搜索树的性质。
堆是一种特殊的完全二叉树,常用于实现优先队列。其特殊性主要体现为局部有序性,即最小堆对应的完全二叉树中所有内部结点的值均不大于其左右子结点的关键码值,而一个结点与其兄弟之间没有必然的联系。堆的插入和删除操作必须保持最小堆的堆序性质不变,因此在地中插入和删除一个元素时需要调整父子结点的位置关系。建堆过程是一个从下至上不断筛选自过程。
结点的带权路径长度是指从根结点到该结点的路径长度与结点权值的乘积。Huffman树用贪心法构造带权外部路径长度最小的二叉树,在信息编码中有广泛的应用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值