二叉树的右视图:
在牛客的刷题过程中,总是遇到二叉树的遍历问题,做下总结,方便后面回顾。每次遇到二叉树的递归总是有点虚,似乎怕想不明白,但是其实就是几种情况,总结完就没问题。目前我看到的有,三种遍历的方式,求二叉树的深度,求二叉树的结点的个数,求叶子结点的个数,交换左右子树,销毁、复制一棵二叉树。随着牛客的做下来,慢慢在这个博客里面完善。
常用的是递归调用。其实可以把一整课二叉树看成是三个结点,每一个小的分支都是遵守同一种访问规律。
1. 三种遍历方式的总结:
首先是先序遍历,无非是先访问根节点,再访问左结点,最后访问右结点。那么访问的过程肯定是先访问正中间的根节点,再访问根节点的左结点,再访问第一个左结点的左结点。。。以此类推,直到没有左结点了,便访问最后一个左结点的右结点,由此往上,递推回去。感觉比较难讲清,看递归代码和自己画个图出来最明显。
void Preorder(BTNODE *T)
{
if(T!= NULL){
VISIT(T) #对T的操作 #根先操作
Preorder(T->left)
Preorder(T->right)
}
其次是中序遍历,中序遍历即先访问左结点,再访问根节点,最后访问右结点,对每一个二叉树的分支都是这么操作。与上述先序遍历差不多,只是左结点先通过VISIT(T)操作,每一个分支的根节点其实都是上一个分支的左结点或者是右结点,所以其实只是对左右结点进行操作,串联其所有的结点。
Void inorder(BTNode *t)
{
if(t != NULL)
inorder(t->left)
Visit(t) #对结点t的操作 左结点先操作,再根,再右节点
inorder(t->right)
}
最后是后序遍历,先访问左结点,再访问右结点,最后访问根节点。看代码区别很明显,也容易记住。
Void backorder(BTNNode *t){
If(t!=NULL)
backorder(t->left)
backorder(t->right)
Visit(t)
}
2.求二叉树的深度
def maxdepth(pRoot):
if not pRoot:
return 0
return max(maxdepth(pRoot.left)+1, maxdepth(pRoot.right)+1)
还有可以用层次遍历:
class Solution(object):
def maxDepth(self, root):
queue = []
if not root:
return 0
queue.append(root)
depth = 0
while queue:
tmp = []
for i in queue:
if i.left:
tmp.append(i.left)
if i.right:
tmp.append(i.right)
depth += 1
queue = tmp
return depth
3.求二叉树的结点个数
nodes = 0
def node(pRoot):
if not pRoot:
return 0
nodes += 1
node(pRoot.left)
node(pRoot.right)
return nodes
4.求二叉树的叶子结点个数
Status LeafCount(BiTree T){
if(T){
if(T->lchild==NULL&&T->rchild==NULL){
Count++;
}
if(LeafCount(T->lchild))
if(LeafCount(T->rchild))
return 1;
}
else return 1;
}
# 第二种
nodes = 0
def node(pRoot):
if not pRoot:
nodes += 0.5
return nodes
node(pRoot.left)
node(pRoot.right) #一个叶子节点加了两次
return nodes
def leavenode(pRoot):
if not pRoot:
return 0
node(pRoot)
return nodes
5.复制一棵二叉树
复制一棵二叉树也是递归,采用先序遍历。
class Treenode():
def __init__(self):
self.val = None
self.left = None
self.right = None
def copy(head):
if not head:
return
head1 = Treenode()
head1.val = head.val
head1.left = copy(head.left)
head1.right = copy(head.right)
return head1