引言
本章将介绍非线性结构——二叉树,相对于之前的线性表、栈、队列等数据结构,二叉树中的元素有着更为复杂的联系,因此也存在更复杂的操作。
二叉树的概念
作为最简单的树形结构,二叉树中每个结点最多关联两个后继节点,且结点分为空、左、右。
官方定义:二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
以下为二叉树的几个较为重要的概念:
-
不包含任何结点的二叉树称为空树,只包含一个节点的二叉树称为单点树(类链表)
-
一棵二叉树的根节点成为该树的子树根结点的父结点;与之对应,子树的根结点成为二叉树树根结点的子结点
-
父结点到子结点的连线称为边,方向为父→子
-
基于父子关系可以定义其传递关系,称为祖先/子孙关系,它决定了一个结点的祖先节点/子孙结点;父结点相同的两个子结点称为兄弟结点
-
如果一个结点不含有子结点,则称为叶
-
一个结点的子结点个数称为度,度不为0的结点称为分支结点
-
从一个祖先节点到一个子孙结点都存在一系列边,这一系列边构成了树的一条路径,路径边的条数称为该路径的长度
-
二叉树是一种层次结构,规定根节点的层次为1,其子结点看作下一层元素
-
二叉树的最大层数为高度
基本性质
二叉树的性质如下:
-
在非空二叉树第i层中至多有2^i个结点
-
高度为h的二叉树至多有2^(h+1)-1
-
对于任何非空二叉树T,如果其叶结点的个数为n0,度数为2的结点个数为n2,那么n0=n2+1
特殊结构
二叉树的特殊结构主要有以下几种:
-
满二叉树:如果二叉树中所有分支结点的度数都为2,则称它为一个满二叉树(如下图,图片来源,侵删);满二叉树叶子节点比分支节点多一个
-
完全二叉树:除了最后一层以外,所有层都是满的(如下图,图片来源,侵删)
-
扩充二叉树:将一个二叉树填入足够多的空叶子,使其原有结点都变为度为2的结点(如下图)。
二叉树的基本操作与实现
二叉树由结点构成,每个结点中存储着元素和指针域,而操作也是围绕于此进行,以下是二叉树的重要操作:
-
创建二叉树
-
判断是否为空树
-
求二叉树的结点个数
-
获取根节点的数据
-
获取二叉树的左子树
-
获取二叉树的右子树
-
遍历二叉树(先序、中序、后序以及层序遍历)
Python实现:
from collections import deque
class BinaryTree():
def __init__(self, val=None, left=None, right=None, height=0):
self.val = val
self.left = left
self.right = right
def preorder(self):
if not self.val:
return
print(self.val, end=' ')
if self.left:
self.left.preorder()
if self.right:
self.right.preorder()
def inorder(self):
if not self.val:
return
if self.left:
self.left.inorder()
print(self.val, end=' ')
if self.right:
self.right.inorder()
def postorder(self):
if not self:
return
if self.left:
self.left.postorder()
if self.right:
self.right.postorder()
print(self.val, end=' ')
def levelorder(self):
if not self:
return []
d = deque([self])
res = []
while d:
n = len(d)
for i in range(n):
node = d.popleft()
res.append(node.val)
if node.left:
d.append(node.left)
if node.right:
d.append(node.right)
return res
def height_count(self):
if not self:
return 0
if not self.left and not self.right:
return 1
if self.left and not self.right:
return self.left.height_count() + 1
if not self.left and self.right:
return self.right.height_count() + 1
return max(self.left.height_count(), self.right.height_count()) + 1
class Solution:
res = 0
def maxDepth(self, root):
tmp = 0
self.DFS(tmp, root)
return self.res
def DFS(self, tmp, tree):
if not tree:
self.res = max(self.res, tmp)
return
tmp += 1
self.DFS(tmp, tree.left)
self.DFS(tmp, tree.right)
if __name__ == '__main__':
tree1 = BinaryTree(3)
tree2 = BinaryTree(6)
tree3 = BinaryTree(1, tree1, tree2)
tree4 = BinaryTree(2, tree2, tree1)
root = BinaryTree(10, tree3, tree4)
root.preorder()
print('\n')
root.inorder()
print('\n')
root.postorder()
print('\n')
print(root.levelorder())
print('\n')
print(root.height_count())