1. プリオーダー、インオーダー、ポストオーダーでの再帰的書き込み
プロローグ
public void preorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);
preorder(root.left, res);
preorder(root.right, res);
}
その後
public static void postOrderRecur(TreeNode head) {
if (head == null) {
return;
}
postOrderRecur(head.left);
postOrderRecur(head.right);
System.out.print(head.value + " ");
}
順番通りに
public static void inOrderRecur(TreeNode head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
2. プレオーダートラバーサル反復法
事前順序トラバーサルの主な特徴は、中央、左、右です。
上記の事前順序トラバーサルは、1 2 4 5 3 6 7 です。1
2 4 がすべて左側のサブツリーであり、次に右側のサブツリーであることは明らかです。トラバーサル後にサブツリーに到達するため、反復で行う必要があるのは、左側のサブツリー ノードのトラバースを維持し、現在の左側のサブツリーのルート ノードを保存することです。左側のサブツリーは終了し、ノードを削除して右側のサブツリーを見つけます。ノード。ここでは、スタックを使用してノードを保存し、対応する順序でノードをポップする必要があります。
2.1 バイナリツリーの事前順序走査
バイナリ ツリーの事前順序トラバーサル
バイナリ ツリーのルート ノード ルートが与えられた場合、そのノード値の事前順序トラバーサルを返します。
入力: root = [1,null,2,3]
出力: [1,2,3]
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while(!stack.isEmpty() || node!=null){
while(node!=null){
res.add(node.val);
// 保存根节点,找到对应的右节点
stack.push(node);
// 处理左子树
node = node.left;
}
// 找到对应的右节点的根节点
node = stack.pop();
// 处理右子树
node=node.right;
}
return res;
}
3. 反復的な順序トラバーサル
特徴: 左、中央、右
要素: 4 2 5 1 6 3 7
これは、毎回左端のサブツリー ノードを走査し、ルート ノードにまだ右のノードがある場合は、逆の順序で一番下のノードを出力すると見ることができます。右に入力し続けると、ノードは一番下に移動します。それ以外の場合は、逆の順序で出力されます。このノードを保存するにはスタックを使用する必要があります。
3.1 二分木のインオーダートラバース
バイナリ ツリーの順序トラバーサル
バイナリ ツリーのルート ノード ルートを指定すると、その順序トラバーサルを返します。
入力: root = [1,null,2,3]
出力: [1,3,2]
通常は同じですが、追加する場合、追加される現在のリンクの最後のノード要素となる点が異なります。
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root ==null) return res;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while(!stack.isEmpty() || node!=null){
while(node!=null){
stack.push(node);
node=node.left;
}
// 此时已经到头了
node = stack.pop();
res.add(node.val);
node=node.right;
}
return res;
}
4. ポストオーダートラバーサル
特徴: 左、右、中央
要素: 4 5 2 6 7 3 1
要素の特徴: 現在のルート ノードの 2 つの子ノードの値を出力し、次にルート ノードを出力する必要があります。しかし、実際の操作では、事後注文の便利な要素を 1 3 7 6 2 5 4 に反転するのは非常に面倒です。これは事前注文と似ていますが、違いは、事前注文が左を横切ることです。最初にノードを探索し、今度は右のノードをトラバースしてから、リスト要素全体を反転する必要があります。
4.1 二分木の事後走査
バイナリ ツリーの事後探索
バイナリ ツリーのルート ノード ルートを指定すると、そのノード値の事後探索を返します。
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = root;
while(!stack.isEmpty() || node!=null){
while(node!=null ){
res.add(node.val);
stack.push(node);
node= node.right;
}
node = stack.pop();
node = node.left;
}
Collections.reverse(res);
return res;
}
ただし、この方法では、関連する事後順序トラバーサル機能は使用されず、事前順序のみが使用されます。
4.2 反復法
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) return res;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode node = null;
while(!stack.isEmpty() || root!=null){
while(root!=null ){
stack.push(root);
root= root.left;
}
root = stack.pop();
// 如果右子树为空或者已经被访问过了,才能添加当前节点值
if(root.right==null || root.right == node){
res.add(root.val);
node=root;
root=null;
}else{
stack.push(root);
root = root.right;
}
}
return res;
}
この方法は少しわかりにくいですが、関連する手順も理解できます。