二叉树基础

本文介绍了树作为一种非线性数据结构,包括树的基本概念如节点、父子关系、高度、深度和层数。重点讲解了二叉树的特性,如满二叉树、完全二叉树,并探讨了链式存储法和数组顺序存储法。此外,还详细阐述了二叉树的前序、中序和后序遍历及其递归实现。
摘要由CSDN通过智能技术生成

树(tree)

树是一种数据结构,不同于栈、队列等线性表结构,树是一种非线性表结构。在树这种数据结构中,元素叫做“节点”,用来连接相邻节点之间的关系叫做“父子关系”。

如下图所示,A节点是B节点的父节点,B节点是A节点的子节点。B、C、D这三节点父节点相同,所以它们互称兄弟节点。E没有父节点,叫做根节点。没有子节点的节点叫做叶节点/叶子节点,如G节点就是叶节点。

 关于“树”,还有三个比较相似的概念:高度(height)、深度(depth)、层(level)。下面是相关定义:

高度和深度看的是边数,而层数看的是节点数。可以通过下面例子来帮助理解。

 二叉树(Binary Tree)

二叉树,顾名思义每个节点最多有两个叉,也就是两个子节点,分别是左子节点和右子节点。下图中的几个都是二叉树。

 

 编号2的二叉树中,叶节点全都在最底层且除叶节点外,每个节点都有左右两个子节点,这种二叉树叫做满二叉树

编号3的二叉树中,叶节点都在最底下两层,最后一层的叶节点都靠左排列,且除了最后一层,其他各层的节点数要达到最大,这种二叉树叫做完全二叉树

下面是完全二叉树的非完全二叉树的例子。

 

 完全二叉树之所被特别关注,是因为二叉树的储存中有重要特性。

存储二叉树,有两种方法,一是基于指针或者引用的二叉链式存储法,二是基于数组的顺序存储法。

下面先来看链式存储法。从图中可以看到,每个节点有三个字段,其中一个存储数据,另外两个是指向左右子节点的指针。大部分二叉树代码都是通过这种结构实现的。

 下面继续来基于数组的顺序存储法。我们把根节点存储在下标i=1的位置,那左子节点存储在下标2i 的位置,右子节点存储在2i+1 的位置。以此类推,B节点的左子节点存储在4的位置,右子节点存储在5的位置。

 刚刚的例子是一个完全二叉树,所以仅仅“浪费”了一个下标为0的存储位置。如果是非完全二叉树,其实会浪费比较多的数组存储空间。比如下面这个例子。

 可以看出,如果某棵二叉树是一课完全二叉树,那用数组存储无疑是最节省内存的一种方式。因为数组存储不需要像链式存储法一样要存储额外的左右子节点的指针。这也是为什么完全二叉树会被单独拎出来的原因,也是为什么完全二叉树要求最后一层的子节点都靠左的原因。

堆就是一种完全二叉树,最常用的存储方式就是数组。

二叉树的遍历

将二叉树所有节点都遍历打印出来的方法有三种,前序遍历中序遍历后序遍历。其中,前、中、后序表示的是节点与它的左右子节点遍历打印的先后顺序。

前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。

中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。

后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。

 实际上,二叉树的前、中、后序遍历就是一个递归的过程。比如,前序遍历,其实就是先打印根节点,然后再递归地打印左子树,最后递归地打印右子树。写递归代码的关键,就是看能不能写出递推公式,而写递推公式的关键就是,如果要解决问题 A,就假设子问题 B、C 已经解决,然后再来看如何利用 B、C 来解决 A。所以,我们可以把前、中、后序遍历的递推公式都写出来。


前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)

中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)

后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值