文章目录
数与二叉树
1. 数
1.1 数的定义
-
数是 n(n≥0)个结点的有限集。
-
数的定义是一个递归定义
1.2 数的基本术语
- 根节点:非空树中无前驱结点的结点
- 结点的度:结点拥有的子树的数量
- 树的度:树中结点的度的最大值
- 结点的孩子:结点的子树的根称为该结点的孩子,该结点称为孩子的双亲
- 兄弟
- 结点的祖先:从根到该结点所经分支上的所有结点
- 结点的子孙:以某结点为根的子树中的任一结点
- 结点的层次
- 堂兄弟:双亲在同一层次的结点
- 树的深度
- 有序树和无序树
- 森林:m (m≥0) 棵互不相交的树的集合
2. 二叉树
2.1 二叉树的定义及其特点
- 二叉树的定义:二叉树是 n (n≥0) 个结点的有限集,它或者是空集 (n = 0),或者由一个根结点及两棵不相交的分别称作这个根的左子树和右子树的二叉树组成
- 二叉树的特点:
- 每个结点最多有两孩子(二叉树中不存在度大于2的结点)
- 子树有左右之分,次序不能颠倒
- 二叉树可以是空集合,根可以有空的左子树或空的右子树
2.2 二叉树的性质
-
性质一:在二叉树的第 i 层上至多有 2 ^(i - 1) 个结点 (i ≥1)。
- 性质一告诉我们在每层上的结点与层数之前的关系
- 在第i层上,最少有1个结点,否则,这一层就不存在
-
性质二:深度为k的二叉树最多有(2^k)-1个结点(k ≥1)。
- 性质二讨论的是二叉树的深度k和数的结点n之间的关系
- 深度为k的二叉树至少有k个结点(根据性质一的推论,一层一个结点)
-
性质三:对于任何一颗二叉树T,如果其叶子数为n,度为2的结点数为num,则n = num+1
- 性质三证明思路:
- 假设有sum个结点的二叉树中度为1的结点数为num_1,二叉树中结点的度最大不超过2,则有:sum = n + num_1+num
- 二叉树中,除了根结点,其余结点跟它的双亲都有一个分支,设B为分支总数,则有:sum = B +1
- 分支总数B又等于度为1的分支和度为2的分支的总和,则:B = num_1+2*num
- 于是有 sum = B+1 = num_1+2*num+1
- 结合sum = n+num_1+num得n+num_1+num = num_1+2*num+1
- 化简得n = num+1
- 性质三证明思路:
2.3 满二叉树和完全二叉树
2.3.1 满二叉树的定义及其特点
- 定义:一颗深度为K,且有(2^k)-1个结点的二叉树称为满二叉树
- 特点:每一层的结点数都达到最大,叶子全部都在最底层
- 编号规则:从根结点开始(根结点编号为1),自上而下,自左而右
2.3.2 完全二叉树的定义及其特点
- 定义:深度为 k 的具有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 k 的满二叉树编号为 1~ n 的 结点一一对应时,称之为完全二叉树。
- 特点:叶子只可能分布在层次最大的两层上。
2.4 二叉树的存储结构
2.4.1 顺序存储结构
-
完全二叉树:用一组地址连续的单元依次存储自上而下,自左而右存储结点元素
-
实现:
-
#define MSX_TREE_SIZE 100 //最大结点数 typedef TElemType SqBTBiTree[MAX_TREE_SIZE]; SqBiTree bt;
-
-
2.4.2 链式存储结构
-
二叉树结点的构成:数据域(data),左孩子指针(lchild),右孩子指针(rchild)
-
C语言实现:
-
//二叉链表 typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*rchild; //左右孩子指针 }BiTNode,*BiTree;
-
//三叉链表:结点增加一个双亲指针 typedef struct BiTNode { TElemType data; struct BiTNode *lchild,*parent,*rchild; //左右孩子指针以及双亲指针 }BiTNode,*BiTree;
-
2.5 遍历二叉树
- 二叉树的遍历概念:顺着某一条搜索路径一次访问每一个结点,且每个结点都被访问且仅访问一次
- 二叉树遍历的目的:得到树中所有结点的一个线性排列
- 遍历方法(规定先左后右):D表示根结点,L表示左子树,R表示右子树
- DLR :先序遍历(先访问根结点)
- LDR :中序遍历(访问完左子树再访问根结点)
- LRD :后序遍历(最后访问根结点)
2.5.1 先序遍历二叉树的操作定义
-
算法思路:
若二叉树为空,则空操作,否则执行下面操作
访问根结点
先序遍历左子树
先序遍历右子树
-
从上面的算法思路可以知道,这是一个递归算法,递归得使用先序遍历来访问左子树和右子树
-
算法实现:
-
void perorder(BiTree *root) { //判断二叉树是否为空 if(!root) { return ERROR; } Visst(root->data); //访问根结点 perorder(root->lchild); //先序遍历左子树 peroeder(root->rchild); //先序遍历右子树 return OK; } void Visit(BiTree TElemType e) { printf("%d",e); }
-
2.5.2 中序遍历和后序遍历的操作定义
参考先序遍历即可
持续更新ing…