7.2 7.3 二叉树的概念和性质、存储

基本概念

二叉树定义

二叉树的递归定义:

  • 一颗空树或者单个结点构成的树是一颗二叉树;
  • 除此之外,一棵二叉树有两颗互不相交的二叉树(分别称为左子树和右子树)构成。

需要区分二叉树和二次树的概念。二次树一定是二叉树(当然二次树不区分左右孩子),反之不一定成立。因为一棵一边倒的树可以是二叉树,但是二次树必须要求存在一个度为2的结点。
对于满二叉树和完全二叉树只给出形式化描述:满二叉树(full binary tree)是指一棵叶子结点都在树的最下层的二叉树。而完全二叉树(complete binary tree)是指最下面一层的叶子从左往右依次排满。换句话说,完全二叉树的上一层一定是个满二叉树。满二叉树实际上是完全二叉树的一个特殊情况。
对于完全二叉树,当结点有奇数个,则不存在度为1的结点。反之,存在一个度为1的结点(最多只能存在一个)。

二叉树的性质

二叉树的很多性质都能够根据树的性质推出(是树的一种特殊情况)。至于完全二叉树涉及到编号的一些性质,可以简单画图得出。
其中完全二叉树有一条非常重要的性质:

编号为 k 的结点,其左孩子的编号为2k,而右孩子 2k+1 。而父母的编号为 k2


二叉树与普通树的转换

树转化为二叉树

(1)将树中所有相邻的兄弟之间用线连接起来
(2)对树中的每个结点只保留他与长子之间的连线,删除与其他孩子之间的连线。

二叉树转化为普通树

(1)若某个结点是其父母的左孩子,则把该结点的右孩子、右孩子的右孩子等全部用线与其父母连接起来。
(2)删除原二叉树所有双亲结点与右孩子结点之间的连线。

总结

将树转化为二叉树时,实质上是使用了孩子兄弟链法(因为二叉树也是保留两个指针域)。因此,可以认为左孩子是普通树里的孩子链,而右孩子认为是兄弟链。整个的思路大体如此。

森林的处理

森林的处理较为类似,只需要将每棵树转化为二叉树后,将他们的根都当做平行的兄弟来构造一棵新的二叉树(最左边的作为根,其余的依次作为右孩子)。
二叉树分离成森林,则先依次向右找右孩子,将其分离出每一颗树。然后再将每一棵二叉树转化为普通树。


二叉树的存储结构

顺序存储结构

顺序存储结构的核心在于如何使用连续的空间存放一棵二叉树。对于 n 个结点的完全二叉树,可以对结点进行编号,分别为1..n,于是在数组中 A[i] 表示编号为 i 的结点。对于非完全二叉树,如果编号为i的结点不存在,在数组 A 中可以通过设置为特殊值NIL来表示。这样处理以后,可以保证这个数组保存的是一个完全二叉树(尽管具有没有实际值的结点用特殊值 NIL 来表示)
解决了存储问题之后,下面要解决的问题在于,如何表示父母和孩子之间的逻辑关系。对于完全二叉树很显然根据性质,编号为 k 的结点,其左孩子的编号为2k,而右孩子 2k+1 。而父母的编号为 k2 。因此不需要借助指针,直接通过下标的计算就能够完成寻找父母和寻找左右孩子,时间为 O(1)
这种存储方式具有较大的缺陷在于,如果树不是很“平衡”,空结点存储 NIL 也要浪费巨大的空间。这种存储方式通常用在二叉堆上面(堆是一种顺序存储的完全二叉树)。

链式存储结构

二叉树的链式存储结构是使用二叉链来存储的。二叉链是指每个结点使用两个指针域lchildrchild分别用来表示左孩子和右孩子。有时候为了寻找父母和祖先较为方便,也会添加一个parent指针域。
这种存储方式的优点在于空间利用率较高。
一种典型的结点构造方式如下:

template<typename _Ty>
struct BinaryTreeNode{
    _Ty data;
    BinaryTreeNode * lchild;
    BinaryTreeNode * rchild;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值