二叉树基本介绍

1.基本概念

概念(需牢记):

结点的度:一个结点含有子树的个数称为该节点的度。(理解为有几个儿子)如上图A的度为6。

树的度:一颗树中,所有结点度的最大值称为树的度。如上图树的度为6。

叶子结点或终端结点:度为0的结点称为叶结点。如上图BCHI为叶结点。

父节点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:AB的父结点。

子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:BA的孩子结点。

根结点 :一棵树中,没有双亲结点的结点;如上图: A。

结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推 

树的高度或深度 :树中结点的最大层次; 如上图:树的高度为 4
非终端结点或分支结点 :度不为 0 的结点; 如上图: D E F G... 等节点为分支结点
兄弟结点 :具有相同父结点的结点互称为兄弟结点; 如上图: B C 是兄弟结点

堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:HI互为兄弟结点  

结点的祖先 :从根到该结点所经分支上的所有结点;如上图: A 是所有结点的祖先
子孙 :以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是 A 的子孙
森林 :由 m m>=0 )棵互不相交的树组成的集合称为森林

2.二叉树(重点)

2.1二叉树的概念

1.二叉树不存在度大于2的结点。

2.二叉树的子树有左右之分,且次序不可颠倒,二叉树是有序树。

3.二叉树有且仅有以下几种情况组成:空树、只有根节点、只有左子树、只有右子树、左右子树都存在

2.2两种特殊的二叉树

1.满二叉树:如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵 二叉树的层数为K,且结点总数是2^{k}-1,则它就是满二叉树

2.完全二叉树: 对于深度为 K 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 K 的满二叉树中编号从 0 n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

2.3二叉树的性质(重点,牢记)

1.若规定根节点的层数为1,则一颗非空二叉树的第i层上最多2^{i-1}(i>0)个结点。

2.若规定只有根结点的二叉树的深度为1,则深度为k的二叉树最大节点数是2^{k}-1(k>=0)

3.对任何一颗二叉树,如果其叶结点个数为n0,度为2(有两个儿子)的非叶结点个数为n2,则有n0=n2+1。

4.具有n个结点的完全二叉树的深度k为\log_{2} (n+1) 上取整。

5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i的结点有

        若i>0 双亲序号: (i-1)/2 i=0 i 为根结点编号 ,无双亲结点
        若2i+1<n ,左孩子序号: 2i+1 ,否则无左孩子
        若2i+2<n ,右孩子序号: 2i+2 ,否则无右孩子
详见习题:
1. 某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )
A 不存在这样的二叉树
B 200
C 198
D 199
解析:n0=叶子结点,n2=度为2的结点。n0=n2+1,所以n0=199+1=200。选B
2. 在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
A n
B n+1
C n-1
D n/2
解析: 2n可以保证该树一定是偶数个结点,所以一定有一个单侧的边。故n1=1;总的结点个数2n=n0+n1+n2=n0+n2+1。又因为n0=n2+1,所以2n=n0+n0-1+1,所以n0=n。选A
3. 一个具有 767 个节点的完全二叉树,其叶子节点个数为()
A 383
B 384
C 385
D 386
解析: 767=n0+n1+n2=n0+n2=n0+n0-1,所以n0=768/2,选B
4. 一棵完全二叉树的节点数为 531 个,那么这棵树的高度为( )
A 11
B 10
C 8
D 12
解析:深度为log2(531),2的10次方是1024,9次方是512,向上取整,所以是10,选B

2.4二叉树存储

二叉树的存储结构 分为: 顺序存储 类似于链表的链式存储
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式 ,具体如下:
// 孩子表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的根节点
}

2.5二叉树的遍历

2.5.1前中后序列遍历

三种遍历方式:前序遍历、中序遍历、后序遍历。

前序遍历(Preorder Traversal):根结点、根的左子树、根的右子树。

中序遍历(Inorder Traversal):根的左子树、根结点、根的右子树。

后序遍历(Postorder Traversal):根的左子树、根的右子树、根结点。

2.5.2层序遍历

从上到下、从左到右。

习题测试

1. 某完全二叉树按层次输出(同一层从左到右)的序列为 ABCDEFGH 。该完全二叉树的前序序列为 ()
A: ABDHECFG B: ABCDEFGH C: HDBEAFCG D: HDEBFGCA
解析:正常画就可以,第一层是A,第二层是BC,依次类推,可以画出树。前序结果为A
2. 二叉树的先序遍历和中序遍历如下:先序遍历: EFHIGJK; 中序遍历: HFIEJKG. 则二叉树根结点为 ()
A: E B: F C: G D: H
解析: 先序遍历,可以确定根结点。E为根结点,则中序遍历中,E左边的为左子树,E右边的为右子树。再将F作为根结点,再进行左右切分,直到先序遍历全部用完,则可画出树。结果为A。
3. 设一课二叉树的中序遍历序列: badce ,后序遍历序列: bdeca ,则二叉树前序遍历序列为 ()
A: adbce B: decab C: debac D: abcde
解析: 后序遍历与先序遍历功能类似,都是确定根结点位置,然后将中序遍历切分的。结果为D
4. 某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出 ( 同一层从左到右 ) 的序列为 ()
A: FEDCBA B: CBAFED C: DEFCBA D: ABCDEF
解析:同理,在后序遍历中找头结点,在中序遍历中做切分,最终结果为A
### 二叉树在C++中的基本概念和实现 #### 什么是二叉树二叉树是一种常见的非线性数据结构,其特点是每个节点最多有两个子节点:左子节点(`lchild`)和右子节点(`rchild`)。这种特性使得二叉树非常适合用于表达层次关系以及解决许多复杂问题。 #### 二叉树的链式存储结构 在C++中,通常通过定义一个节点类来描述二叉树的结构。每个节点包含三个部分: 1. **数据域 (`data`)**:用来存储节点的实际数据。 2. **左指针 (`lchild`)**:指向当前节点的左子节点。 3. **右指针 (`rchild`)**:指向当前节点的右子节点。 以下是基于上述描述的一个典型二叉树节点定义[^1]: ```cpp typedef struct Node { char data; // 数据域 struct Node *lchild, *rchild; // 左子树和右子树 } *BiTree, BiNode; ``` 对于更通用的情况,在C++中可以通过模板类的方式支持多种类型的节点数据[^2]。例如: ```cpp template <class T> struct Node { T data; // 泛型数据域 Node<T> *lchild; // 左子节点指针 Node<T> *rchild; // 右子节点指针 }; ``` #### 封装二叉树的操作 为了便于管理和操作二叉树,可以将其封装在一个类中。下面是一个简单的 `BinaryTree` 类的设计: ```cpp template <class T> class BinaryTree { private: Node<T>* root; // 根节点 size_t size; // 当前二叉树的规模 public: BinaryTree() : root(nullptr), size(0) {} // 构造函数初始化为空树 ~BinaryTree(); // 析构函数释放内存 void insert(T value); // 插入新节点 bool search(T value); // 查找指定值是否存在 int depth(); // 获取二叉树深度 size_t countNodes(); // 统计节点总数 size_t leafCount(); // 统计叶子节点数量 }; ``` #### 关键功能实现 ##### 计算二叉树深度 计算一棵二叉树的最大深度可以通过递归方式完成。具体逻辑是从根节点出发,分别求解左右子树的高度并取较大者加一[^5]。 ```cpp int getDepth(Node<T>* node) const { if (node == nullptr) return 0; int leftDepth = getDepth(node->lchild); int rightDepth = getDepth(node->rchild); return std::max(leftDepth, rightDepth) + 1; } ``` ##### 节点统计 要获取整个二叉树的总节点数,同样采用递归策略。每次访问到一个有效节点时累加计数值。 ```cpp size_t getNodeCount(Node<T>* node) const { if (node == nullptr) return 0; return getNodeCount(node->lchild) + getNodeCount(node->rchild) + 1; } ``` ##### 叶子节点统计 叶子节点是指那些既无左子也无右子的节点。因此只需判断某个节点是否满足此条件即可。 ```cpp size_t getLeafCount(Node<T>* node) const { if (node == nullptr) return 0; if (node->lchild == nullptr && node->rchild == nullptr) return 1; return getLeafCount(node->lchild) + getLeafCount(node->rchild); } ``` #### 总结 以上展示了如何利用C++语言构建和操作二叉树的基础框架及其核心方法。这些技术不仅限于理论层面的应用,还广泛应用于诸如文件系统导航、编译器优化等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值