一、二叉树基本理论知识
(一)二叉树的种类
满二叉树
定义:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
完全二叉树
定义:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
二叉搜索树
前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树。
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树
下面这两棵树都是搜索树
平衡二叉搜索树
定义:平衡二叉搜索树又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
如图:
(二)二叉树的存储方式
链式存储
链式存储方式为指针
顺序存储
顺序存储的方式为数组
用数组来存储二叉树的遍历方式是:如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。
但是用链式表示的二叉树,更有利于我们理解,所以一般我们都是用链式存储二叉树。
(三)二叉树的遍历方式
二叉树主要有两种遍历方式:
深度优先遍历:先往深走,遇到叶子节点再往回走。
广度优先遍历:一层一层的去遍历。
- 深度优先遍历
前序遍历(递归法,迭代法)
中序遍历(递归法,迭代法)
后序遍历(递归法,迭代法) - 广度优先遍历
层次遍历(迭代法)
这里前中后,其实指的就是中间节点的遍历顺序,只要记住前中后序指的就是中间节点的位置就可以了。
看如下中间节点的顺序的图示
- 前序遍历:中左右
- 中序遍历:左中右
- 后序遍历:左右中
(四)二叉树结点定义代码
链式存储的二叉树节点的定义方式
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
二、二叉树递归遍历
迭代vs递归?
递归是重复调用函数自身实现循环。迭代是函数内某段代码实现循环,循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。
递归循环中,遇到满足终止条件的情况时逐层返回来结束。迭代则使用计数器结束循环。当然很多情况都是多种循环混合采用,这要根据具体需求。
递归算法的三个要素
首先确定递归算法的三个要素:
- 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
- 确定终止条件: 写完了递归算法,运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
144. 二叉树的前序遍历
代码
二叉树定义
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
前序遍历
# 前序遍历-递归-LC144_二叉树的前序遍历
class Solution():
def preorderTraversal(self, root):
# 保存结果
result = []
def traversal(root):
if root == None:
return
result.append(root.val) # 前序
traversal(root.left) # 左
traversal(root.right) # 右
traversal(root)
return result
因为root.left在root.right上面所以只有当left全部执行完了的时候才会考虑右边,因此符合“中——左——右”
94. 二叉树的中序遍历
代码
中序遍历
# 中序遍历-递归-LC94_二叉树的中序遍历
class Solution:
def inorderTraversal(self, root):
# 记录结果
result=[]
def Traversal(root):
if root is None:
return
Traversal(root.left)
result.append(root.val)
Traversal(root.right)
Traversal(root)
return result
145. 二叉树的后序遍历
代码
后序遍历
# 后序遍历-递归-LC145_二叉树的后序遍历
class Solution:
def postorderTraversal(self, root):
result=[]
def Traversal(root):
if root is None:
return
Traversal(root.left)
Traversal(root.right)
result.append(root.val)
Traversal(root)
return result