二叉树的先序、中序、后序遍历的递归及非递归形式以及一些树的题目

二叉树的节点遍历顺序,节点遍历顺序是不变的,问题在于将打印节点的语句放在哪里,因此将打印时机放在第几次来到这个节点会造成遍历顺序的不同;第一次来到这个节点,被称作先序遍历,第二次来到这个节点被称作中序遍历,第三次来到这个节点被称作后序遍历!

递归式的二叉树遍历,每一个节点都将出现3次!

非递归的先序遍历:

stack

弹出并打印当前节点,针对于当前节点,以先右后左的顺序将节点入栈,再返回弹出,依次操作。树是从上到下的,但是无法返回,采用栈有可以从底层回到上级的优势!

非递归版中序遍历:

对于当前节点,会将自己的左边界都压入栈中

当前节点为空,从栈弹出打印,弹出的这个节点即被称作当前节点,然后当前节点右节点变为当前节点

若当前节点不为空,当前节点入栈,然后当前节点左节点变为当前节点

对于,需要都是false才是false

整棵树可以被左边界分解的

3.后续遍历:

比较难实现,因为前两种遍历方式只要求访问这个节点两次。

沃尼玛,这也太特么牛逼了!改一下压入顺序,再借用一个栈来辅助!

用两个栈

极客写法:一个栈,孔乙己回字有几种写法

题目3:后继节点

后继节点:中序遍历中一个节点的下一个节点被称作后继节点

代价比较高的方式:通过父节点返回至根节点,然后根据根节点进行中序遍历,就找到了

怎么根据两节点间的距离找到?而不是遍历整棵树来找到!

寻找方法:

如果当前节点有右子树的,整个右子树上最左的节点

1.若当前节点无右子树的,且其为父节点的右孩子,则一直向上,直到当前节点是其父节点的左孩子,这个父节点即为后继节点

2若当前节点无右子树的,若其为父节点的左孩子,则其父节点即为后继节点

整棵树的最右节点没有后继节点!

树存在于内存中,二叉树的序列化和反序列化:

关机后,指针没了,如何存成文件,再将其构造出来

先序遍历,序列化,输出成string,

!和#存在的原因

反序列化:上?

怎么序列化的,就怎么反序列化

按层序列化

牛客后台,用字符串来比对树的结果

按层序列化,不要忽略空,如何序列化,就如何反序列化,不要忽略空!

题目:判断一棵二叉树是否是平衡二叉树

平衡二叉树:这棵树的任意一个节点的左子树和右子树的高度差不超过1,解决效率问题的,平衡性很重要

红黑树无法手撸,高手,也得特么1h,举报他!

红黑树:是什么?怎么用?和其他平衡树的区别有哪些?相同点有哪些?优点有哪些?调整有哪些?

套路:递归函数很有用(一个节点会转三次,先来,左走一圈回来、右走一圈又回来)

如何判断一棵树是否是平衡树?

设计递归返回结构:

递归函数的返回值:包含高度和是否平衡

列出可能性,整理出返回类型,整个递归过程按照同样的结构得到子树的信息

非常套路化的问题

空树是平衡的,高度为0!

任何情况下,返回false时,高度已经没有意义了!

主函数:

高度与是否平衡揉成一个值!

列出可能性,整理出返回类型,设计递归函数,左树返信息,右树返信息,本层加工信息,返回上一级,结构完全一致

树形DP

平衡二叉树会被怎么用?(AVL树、红黑树、傻逼树,某一种平衡性的二叉树)

平衡性:效率问题

 

搜索二叉树:这个树上任意节点的左子树都比它小,右子树都比它大

二叉树中序遍历的结果是升序的,是搜索二叉树(不含重复节点,用内部包含的方式来解决重复节点的问题)

判断是否是搜索二叉树,用中序遍历的非递归版本判断,中序遍历节点是依次升序的,就是搜索二叉树

通常,搜索二叉树是不出现重复节点的,改成非递归遍历,递归版自己改

 

判断一棵树是否是完全二叉树(跟值没关系),是左满的树:

按层遍历:

1.任一个节点有右孩子无左孩子,那么它一定不是完全二叉树

2.如果一个节点不是孩子双全(那么有两种情况,有左无右,或都没有),这种节点后面的节点都必须是叶节点,否则为false

有变量:开启了一个阶段

有一些逻辑上的包含问题!

Q和DQ(两种队列)?

Q,从头进,从尾出

DQ,头进出,尾进出

都可以用双端链表来实现

数组能当堆来使用,二叉树结构来实现堆,增删改查的时间复杂度可以达到o(logN)

二叉树实现堆的好处:

没有空间浪费

优先级队列==堆

题目8:已知一棵完全二叉树,求其节点的个数,要求时间复杂度低于O(N)

高度就是几层

先遍历出这棵树的左边界,O(logN)的代价

判断右子树的左边界是否是到了最后一层,到了,与没到是两种情况!

到了,左子树是满的,没到,右子树是满的

满树节点个数:2*(高度)-1

1<<n,2的n次幂!

时间复杂度:

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我明白了。这是一道关于二叉树的综合题目,我会尽力回答你的问题。 首先,根据输入的完全二叉树先序序列,我们可以通过递归的方式建立这棵。具体来说,我们可以按照先序序列的顺序逐个读取结点,如果读到的是一个实结点,则创建一个新结点并将其赋值为当前读取的结点;如果读到的是一个虚结点,则直接返回 NULL。在创建完当前结点后,我们可以递归地创建其左子,最终返回当前结点。 代码如下: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def build_tree(preorder): n = len(preorder) if n == 0: return None root = TreeNode(val=preorder[0]) if n == 1: return root left_preorder = [] right_preorder = [] i = 1 while i < n: if i % 2 == 1: left_preorder.append(preorder[i]) else: right_preorder.append(preorder[i]) i += 1 root.left = build_tree(left_preorder) root.right = build_tree(right_preorder) return root ``` 接下来,我们可以实现先序中序后序遍历递归操作。其中,先序遍历的操作很简单,只需要按照“根左”的顺序遍历整棵即可;中序遍历和后序遍历的操作可以根据递归的顺序进行调整。 代码如下: ```python def preorder_traversal(root): if root is None: return [] res = [root.val] res += preorder_traversal(root.left) res += preorder_traversal(root.right) return res def inorder_traversal(root): if root is None: return [] res = inorder_traversal(root.left) res += [root.val] res += inorder_traversal(root.right) return res def postorder_traversal(root): if root is None: return [] res = postorder_traversal(root.left) res += postorder_traversal(root.right) res += [root.val] return res ``` 此外,我们还可以实现中序遍历的非递归操作。具体来说,我们可以使用一个栈来模拟递归的过程。对于当前结点,如果其左子非空,则将其入栈,并继续遍历左子;否则,输出当前结点的值,并遍历其。当栈为空时,遍历结束。 代码如下: ```python def inorder_traversal_iter(root): res = [] stack = [] while root is not None or len(stack) > 0: while root is not None: stack.append(root) root = root.left if len(stack) > 0: node = stack.pop() res.append(node.val) root = node.right return res ``` 最后,我们可以求出的高度、叶子结点个数和结点总数。其中,的高度可以通过递归地计算左子的高度,然后取其较大值并加一得到;叶子结点个数可以通过递归地计算左子的叶子结点个数,然后相加得到;结点总数可以通过递归地计算左子结点总数,然后加一得到。 代码如下: ```python def tree_height(root): if root is None: return 0 left_height = tree_height(root.left) right_height = tree_height(root.right) return max(left_height, right_height) + 1 def leaf_node_count(root): if root is None: return 0 if root.left is None and root.right is None: return 1 return leaf_node_count(root.left) + leaf_node_count(root.right) def node_count(root): if root is None: return 0 return node_count(root.left) + node_count(root.right) + 1 ``` 综上所述,我们可以通过以上代码实现对二叉树的各种操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值