二叉树介绍与代码实现

1 树的基本概念

1.1 树的形式定义
T={D,R}
  • D为树T中包含n个结点的有限集合,R为树中结点之间关系的集合。
  • 当n=0时,树为空树;当n>0时,R是D上某个二元关系的集合,满足以下条件:
  • 有且仅有一个结点,称为根结点,该结点没有直接前驱结点;
  • 除根结点外,每个结点有且仅有一个前驱结点;
  • D中每个结点可以有零个或多个后继结点;
1.2 树的递归定义
  • 树是由n(n≥0)个结点组成的有限集T。
  • 当n=0时,它是一个空树;当n>0时,它满足两个条件:
  • 有且仅有一个特定的结点,称为根结点。
  • 除根结点以外的其余结点分为m个(m≥0)互不相交的有限集T1、T2、……Tm,其中每个集合又都是一棵树,称T1、T2、……Tm为根结点的子树。
1.3 树的基本术语
  1. 结点:树的数据元素
  2. 结点的度:该结点的分支的个数
  3. 树的度:树中所有结点的度的最大值
  4. 结点的层次:从根到该结点的层数(根结点算第一层)
  5. 树的深度:所有结点的层次的最大值
  6. 根结点:在非空树中,无前驱结点的结点
  7. 分支结点:度不为0的结点
  8. 叶结点:度为0的结点
  9. 孩子结点:结点的子树的根
  10. 双亲结点:孩子结点的根结点
  11. 兄弟结点:具有共同双亲的结点
  12. 堂兄弟结点:双亲互为兄弟的结点
  13. 祖先结点:从根到该结点的所经历的所有结点
  14. 子孙结点:以某结点为根的子树中的任一结点
1.4 二叉树的递归定义

二叉树是结点的有限集合,这个有限集,或为空集,或由一个根结点及两棵互不相交的,分别叫作这个根的左子树和右子树的二叉树组成。

【注意】二叉树不是树的特殊情况。

1.5 存储方法

双亲表示法——求父结点方便
孩子表示法——求子结点方便
双亲孩子表示法—求父结点和子结点方便
二叉树表示法——把一个普通树转化成二叉树来存储

1.6 满二叉树VS完全二叉树

满二叉树

  • 定义:深为k且有 2 k − 1 2^k-1 2k1个结点的二叉树。
  • 编号:约定编号从根开始,自上而下,自左而右,给二叉树中的每个结点一个从1开始的连续的编号。

完全二叉树

  • 定义:深为k且有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应。

在这里插入图片描述

满二叉树是完全二叉树,反之则不一定!

2 二叉树的性质

  1. 在二叉树的第 i 层上至多有 2 i − 1 2^{i-1} 2i1个结点 ( i ≥ 1 i\geq1 i1)
    在这里插入图片描述

证明:
(1)i=1时,只有一个根结点, 2 i − 1 2^{i-1} 2i1 = 2 0 2^0 20= 1,结论正确;
(2)假设n=k-1命题成立,即第k-1层上至多有 2 k − 2 2^{k-2} 2k2 个结点,则当n=k时,每个结点至多有两棵子树;
k层结点最多为k-1层的2倍,故 s < = 2 ∗ 2 k − 2 = 2 k − 1 s<=2*2^{k-2}=2^{k-1} s<=22k2=2k1,第i层至多有 2 i − 1 2^{i-1} 2i1 个结点;
(3)由归纳法,即得证。


  1. 深度为 k 的二叉树至多有 2 k − 1 2^k-1 2k1个节点( k ≥ 1 k\geq1 k1)

20+21+…+2k-1=2k-1(利用等比数列求和公式得到结果)


  1. 对任何一颗二叉树 T,如果其终端结点树为 n 0 n_0 n0,度为 2 的结点数为 n 2 n_2 n2,则 n 0 n_0 n0 = n 2 n_2 n2+1

证明:
终端结点数就是叶结点数了,而一颗二叉树,除了叶结点外,剩下的就是度为 12 的结点数了,我们设 n 1 n_1 n1 为度是 1 的结点数,则树 T 的总结点数为

n = n 0 n_0 n0 + n 1 n_1 n1 + n 2 n_2 n2

再换一个角度,数一下二叉树中连接线的总数,由于根节点没有双亲,所以一个二叉树中,连接线数等于结点树-1, n 1 n_1 n1 的度为 1 所以它仅有一条连接线, n 2 n_2 n2同理,代数表达式就是

n − 1 n-1 n1 = n 1 n_1 n1 + 2 n 2 2n_2 2n2

再结合等式

n = n 0 n_0 n0 + n 1 n_1 n1 + n 2 n_2 n2

推导出

n 0 n_0 n0 + n 1 n_1 n1 + n 2 n_2 n2-1 = n 1 n_1 n1 + 2 n 2 2n_2 2n2

所以:

n 0 n_0 n0 = n 2 n_2 n2 + 1


  1. 具有 n 个结点的完全二叉树的深度为 [ log ⁡ 2 n ] [\log_2 n] [log2n] + 1 ,([x]代表不大于 x 的最大整数)

证明:
1)对于满二叉树,深度为 k 的满二叉树至多有 2 k − 1 2^k-1 2k1个节点( k ≥ 1 k\geq1 k1)
那么由:

n = 2 k − 1 n=2^k-1 n=2k1

可以倒推

k = log ⁡ 2 ( n + 1 ) k=\log_2(n+1) k=log2(n+1)

2)对于完全二叉树,它的结点数一定少于等于同样深度的满二叉树 2 k − 1 2^k-1 2k1,但一定多于 2 i − 1 − 1 2^{i-1}-1 2i11,即:

2 i − 1 − 1 < n ≤ 2 k − 1 2^{i-1}-1<n\leq2^k-1 2i11<n2k1

所以

2 i − 1 ≤ n < 2 k 2^{i-1}\leq n < 2^k 2i1n<2k

两边取对数:

2 i − 1 ≤ n < 2 k 2^{i-1}\leq n < 2^k 2i1n<2k

k 又是整数:

k = [ log ⁡ 2 n ] + 1 k = [\log_2 n] + 1 k=[log2n]+1


  1. 对于一个有 n 个结点的完全二叉树(或满二叉树)的结点按层序顺序从左到右编号,对任意结点 i 有:

1)如果 i = 1,那么结点 i 为该树的根,无双亲;若 i > 1 ,则其双亲是结点 [i/2]
2)如果 2i > n,则结点无左孩子(结点 i 为叶子结点),否则其左孩子结点是 2i
3)如果 2i + 1 > n,则结点 i 无右孩子,否则其右孩子是结点 2i + 1

3 代码实现

创建二叉树:

#include <stdio.h>
#include <stdlib.h>

typedef char ElementType;
typedef struct Binary {
	ElementType data;
	struct Binary *lchild;
	struct Binary *rchild;
} *BinaryTree;

/* Recursive implementation 1 */
BinaryTree CreateBinaryTree_1(void)
{
	BinaryTree bt;
	char ch;
	scanf("%c", &ch);
	if (ch == '#') {
		bt = NULL;
	} else {
		bt = (BinaryTree)malloc(sizeof(struct Binary));
		bt->data = ch;
		bt->lchild = CreateBinaryTree_1();
		bt->rchild = CreateBinaryTree_1();
	}
	return bt;
}

/* Recursive implementation 2 */
void CreateBinaryTree_2(BinaryTree *bt)
{
	char ch;
	scanf("%c", &ch);
	if (ch == '#') {
		*bt = NULL;
	} else {
		*bt = (BinaryTree)malloc(sizeof(struct Binary));
		(*bt)->data = ch;
		CreateBinaryTree_2(&((*bt)->lchild));
		CreateBinaryTree_2(&((*bt)->rchild));
	}
}

void PreviousOrderTraverse(BinaryTree T)
{
    if (T == NULL) {
        return;
	}
	printf("%c", T->data);
    PreviousOrderTraverse(T->lchild);
    PreviousOrderTraverse(T->rchild);
}

int main(void)
{
	BinaryTree bt;

	// bt = CreateBinaryTree_1();
	CreateBinaryTree_2(&bt);
	
	PreviousOrderTraverse(bt);
	return 0;
}

运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值