二叉树层前中后序

节点定义:

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)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值