数据结构与算法(四)二叉树及其访问方法
昨天我们学习了堆。堆的数据结构其实就是完全二叉树。今天我们就专门学习一下什么是二叉树。
二叉树(Binary tree)
在计算机科学中,二叉树(英语:Binary tree)是每个节点最多只有两个分支(即不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒。
基本性质
- 在二叉树中,第i层的结点总数不超过2^(i-1);
- 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
- 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
- 具有n个结点的完全二叉树的深度为int(log2n)+1
5)给定N个节点,能构成h(N)种不同的二叉树。h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。
完全二叉树(Complete Binary Tree)
若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子结点,并且叶子结点都是从左到右依次排布。
满二叉树 (Full Binary Tree)
- 国内定义
除了叶结点外每一个结点都有左右子结点且叶子结点都处在最底层的二叉树。外观上是一个三角形。
- 国外定义
满二叉树的结点要么是叶子结点,度为0,要么是度为2的结点,不存在度为1的结点。
因此,下图中这个二叉树也是满二叉树。但是按照国内的定义,它却不是满二叉树。
美国以及国际上所定义的满二叉树,即full binary tree,和国内的定义不同,美国NIST给出的定义为:A binary tree in which each node has exactly zero or two children. In other words, every node is either a leaf or has two children. For efficiency, any Huffman coding is a full binary tree.
百度百科 - 满二叉树 https://baike.baidu.com/item/满二叉树
上图为一棵有9个节点且深度为3的二叉树,其根节点的值为2,它既不平衡亦未经过排序
访问二叉树的方法 (Tree Traversals)
我们经常希望访问树中的每一个结点并且查看它的值。有很多常见的顺序来访问所有的结点,而且每一种都有有用的性质。
十分钟弄懂二叉树遍历的视频:
46 小甲鱼-数据结构与算法 46 -二叉树的遍历 https://www.youtube.com/watch?v=GsDlma0jKXo
二叉树遍历主要有四种:
- 前(先)序遍历
- 中序遍历
- 后续遍历
- 层次遍历
在具体看之前,先给大家一个口诀,方便记忆
前序;根左右;中序:左根右;后序:左右根
前序遍历
若二叉树为空, 则返回空,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。【根左右】
遍历的结果是:1、2、4、5、7、8、3、6
class node(object):
def __init__(self,data=None,left=None,right=None):
self.data=data
self.left=left
self.right=right
#前序遍历,**根左右**
def pre_order(tree):
if tree==None:
return
print (tree.data) #根
pre_order(tree.left) #左
pre_order(tree.right) #右
中序遍历
若树为空, 则返回空,否则从根节点开始(之一并不是先访问根节点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。【左根右】
结果是:4、2、7、8、5、1、3、6
#中序遍历,**左根右**
def mid_order(tree):
if tree==None:
return
mid_order(tree.left) #左
print (tree.data) #根
mid_order(tree.right) #右
后序遍历
若树为空, 则返回空,否则从左到右先叶子后结点的方式遍历访问左右子树,最后访问根节点。【左右根】
结果是:4、8、7、5、2、6、3、1
#后序遍历,**左右根**
def post_order(tree):
if tree==None:
return
post_order(tree.left) #左
post_order(tree.right) #右
print (tree.data) #根
层次遍历
概念都不用看了,从上到下,从左到右
结果是:1、2、3、4、5、6、7、8
#层次遍历
def level_order(tree):
if tree==None:
return
q=[]
q.append(tree)
while q:
current=q.pop(0)#根开始
print (current.data)
if current.left!=None:
q.append(current.left)#左
if current.right!=None:
q.append(current.right)#右
访问二叉树的方法图片取自:
【数据结构】树与二叉树的区别 https://blog.csdn.net/lxd8731247769/article/details/49735647
代码:
Python实现二叉树的四种遍历
https://www.cnblogs.com/whb-20160329/p/6663958.html
LeetCode思想实践
#98 Validate Binary Search Tree
判断是不是二叉搜索树(Binary Search Tree)
如果左子树小于根结点,右子树大于根结点,左右子树也是二叉搜索树。那么返回True
首先想到的是中序遍历可以实现【左根右】的遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
res=[]
#中序遍历,**左根右**
def mid_order(root):
if not root:
return
mid_order(root.left)
res.append(root.val)
mid_order(root.right)
mid_order(root)
for i in range(1, len(res)):
if res[i-1] >= res[i]:
return False
return True
#102 Binary Tree Level Order Traversal
https://leetcode.com/problems/binary-tree-level-order-traversal/
返回按层级顺序的遍历,就是一个层次遍历的小升级
class Solution:
def levelOrder(self,tree):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not tree:
return []
q=[]
q.append(tree)
results=[]
while q:
lev_data = []
next_data = []
for node in q:
lev_data.append(node.val)#取根
#是否有左子树
if node.left!=None:
next_data.append(node.left)
#是否有右子树
if node.right!=None:
next_data.append(node.right)
q = next_data
results.append(lev_data)
return results
#107 Binary Tree Level Order Traversal II
https://leetcode.com/problems/binary-tree-level-order-traversal-ii/
就是上一题反向输出,一行代码实现列表翻转
class Solution(object):
class Solution:
def levelOrderBottom(self,tree):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not tree:
return []
q=[]
q.append(tree)
results=[]
while q:
lev_data = []
next_data = []
for node in q:
lev_data.append(node.val)
if node.left!=None:
next_data.append(node.left)
if node.right!=None:
next_data.append(node.right)
q = next_data
results.append(lev_data)
#一行代码实现列表翻转
results = results[::-1]
return results
今天的学习到这里就接近尾声了,但是我们不能忘记前人的付出
- 维基百科 https://zh.wikipedia.org/wiki/二叉树
- 百度百科 - 满二叉树 https://baike.baidu.com/item/满二叉树
- 【数据结构】树与二叉树的区别 https://blog.csdn.net/lxd8731247769/article/details/49735647
- 46 小甲鱼-数据结构与算法 46 -二叉树的遍历 https://www.youtube.com/watch?v=GsDlma0jKXo
- Python实现二叉树的四种遍历 https://www.cnblogs.com/whb-20160329/p/6663958.html
- python中inf这个玩意 https://blog.csdn.net/jeremyjone/article/details/80503488
今天是周日,中午和同学出门吃肯德基,晚上又出门看电影,后两道习题刚开始是在电影院用手机粘贴的代码,看完电影回来又重做的,今天很忙碌,收获也很大,明天继续努力
下次见