节点定义:
class TreeNode{
public $val;
public $left;
public $right;
public function __construct($val){
$this->val = $val;
$this->left = null;
$this->right = null;
}
}
层序遍历:
# 递归
public function levelOrder($root){
$ret = [];
$this->levelOrderRecursive($root, $ret , 0);
return $ret;
}
public function levelOrderRecursive($node, $ret, $level){
if ($node===null) {return ;}
if (!isset($ret[$level])) {
$ret[$level] = [];
} else {
$ret[$level][] = $node->val;
}
$this->levelOrderRecursive($node->left, $ret, $level+1);
$this->levelOrderRecursive($node->right, $ret, $level+1);
}
# 非递归, 用队列 或者 栈实现
# queue, 队列 先进先出 栈后进先出, 层序用队列方便
public function levelOrder($root){
if ($root===null) {
return [];
}
$ret = [];
$queue = [];
array_push($queue,$root);
while(!empty(queue)){
$node = array_shift($queue);
$ret[] = $node->val;
if ($node->left){
array_push($queue, $node->left);
}
if ($node->right){
array_push($queue, $node->right);
}
}
}
先序遍历:
# 先序遍历 递归
public function preOrder($root){
$ret = [];
$ret[]= $root->val;
$this->preOrderHelper($root,$ret);
return $ret;
}
public function preOrderHelper($node, $ret){
if (empty($root)) return ;
$ret[]= $node->val;
if($node->left){
$this->preOrderHelper($root->left,$ret);
}
if ($node->right){
$this->preOrderHelper($root->right,$ret);
}
}
# 先序非递归, 非递归压栈 先右后左
public function preOrder($root){
# 使用栈, 根,左,右
$ret = [];
if(empty($root)) return $ret;
$stack = [];
array_push($stack,$root);
while(!empty($stack)){
$node = array_pop($stack);
$ret[] = $node->val;
if ($node->right){
array_push($stack, $node->right);
}
if ($node->left){
array_push($stack, $node->left);
}
}
return $ret;
}
中序遍历:
# 中序遍历 递归
public function inOrder($root){
$ret = [];
if (empty($root)) return $ret;
$this->inOrderHelper($root,$ret);
return $ret;
}
public function inOrderHelper($node, $ret){
if ($node === null) return ;
if($node->left){
$this->inOrderHelper($root->left,$ret);
}
$ret[]= $node->val;
if ($node->right){
$this->inOrderHelper($root->right,$ret);
}
}
# 中序非递归
public function inOrder($root){
# 使用栈, 左,根,右
$ret = [];
$stack = [];
if(empty($root)) return $ret;
$current = $root;
while(!empty($stack) || $current!==null){
# 遍历找到最左节点
while($current!==null){
array_push($stack,$current);
$current=$current->left;
}
$current = array_pop($stack);
$ret[] = $current->val;
// 转向右子树
$current = $current->right;
}
return $ret;
}
后续遍历:
# 后序 递归
public function postOrder($root){
$ret = [];
if (empty($root)) return $ret;
$this->postOrderHelper($root,$ret);
return $ret;
}
public function postOrderHelper($node, $ret){
if ($node === null) return ;
if($node->left){
$this->postOrderHelper($root->left,$ret);
}
if ($node->right){
$this->postOrderHelper($root->right,$ret);
}
$ret[]= $node->val;
}
#后续非递归
public function postOrder($root){
if(empty($root)) return [];
$ret = [];
$stack = [];
$visited = [];
$current = $root;
while(!empty($stack)||$current!==null){
# 找到最左节点
while($current!==null){
$stack[] = $current;
$current = $current->left;
}
# 最左节点不为空开始处理最右节点
$node = end($stack);
# 如果最左节点有右孩子
if ($node->right){
# 此处加上visited 表示处理过,否则会重复处理
if (!$visited[spl_object_hash($top->right)]]{
$current = $node->right;
$visited[spl_object_hash($top->right)] = 1;
}
} else {
# 没有右孩子 弹出当前节点
$node = array_pop($stack);
$ret[]=$node->val;
}
}
return $ret;
}
后续也可用前序的倒叙.
# 高级货 reverse
public function postOrder($root){
$ret =[];
$stack = [];
array_push($stack,$root);
while(!empty($stack)){
$curr = array_pop($stack);
$ret[] = $curr->val;
if ($curr->left){
$stack[]= $curr->left;
}
if ($curr->right){
$stack[]= $curr->right;
}
}
$ret = array_reverse($ret);
return $ret;
}
# 两个栈
public function postOrder($root){
$ret =[];
$stack = [];
$stack2 = [];
array_push($stack,$root);
while(!empty($stack)){
$curr = array_pop($stack);
$stack2[] = $curr;
if ($curr->left){
$stack[]= $curr->left;
}
if ($curr->right){
$stack[]= $curr->right;
}
}
while(!empty($stack2)){
$node= array_pop($stack2);
$ret[] = $node->val;
}
return $ret;
}
二叉树自底向上遍历的层序遍历
package main
import "fmt"
type TreeNode struct {
Val int
Left *TreeNode // 这里一定要使用指针,否则传参的时候需要实例,而写实例又需要递归写,非常麻烦
Right *TreeNode
}
// 二叉树自底向上遍历
func levelOrderFromBottom(root *TreeNode) [][]int { // 同理, 参数传递的时候也用指针,同时函数值的话是一个副本,会造成复制和浪费
// corner case 判空
if root == nil {
return [][]int{}
}
// 思路进行层序遍历, 然后反转切片
result := [][]int{}
queue := []*TreeNode{root}
for len(queue) > 0 {
length := len(queue)
currentLevel := make([]int, length, length) // currentLevel 遍历的结果存储 当前层node->val
for i := 0; i < length; i++ {
currentLevel[i] = queue[i].Val
if queue[i].Left != nil {
queue = append(queue, queue[i].Left)
}
if queue[i].Right != nil {
queue = append(queue, queue[i].Right)
}
}
result = append([][]int{currentLevel}, result...)
queue = queue[length:]
}
return result
}
func main() {
// 构建一个示例二叉树
// 3
// / \
// 9 20
// / \
// 15 7
root := &TreeNode{Val: 3}
root.Left = &TreeNode{Val: 9}
root.Right = &TreeNode{Val: 20}
root.Left.Left = &TreeNode{Val: 15}
root.Left.Right = &TreeNode{Val: 7}
result := levelOrderFromBottom(root)
fmt.Println("自底向上的层序遍历结果:")
for _, level := range result {
fmt.Println(level)
}
}