基本的な質問タイプのレコード - バイナリ ツリーの順序トラバーサル

基礎が不十分だったので、忘れないようにいくつかの問題形式を記録しました。

1. バイナリツリーの順序トラバーサル

このトラバーサル メソッドについては、ブログで多くの説明を検索できます。ここでは主にコードの実装を記録します。例として次のバイナリ ツリーを取り上げます。
ここに画像の説明を挿入

結果は次のようになります。
ここに画像の説明を挿入

2. 反復法

2.1 トラバーサルプロセス

ここで一時的なスタックを借用します (処理後の最初のアクセス) 対応するルート ノードと左のサブツリーに対応するノードを格納します. ノードはスタックにプッシュされます. 最後に訪問したルート ノードの左のサブツリー ノードが空の場合,対応する要素がスタックの最上位から取得され、操作前にその右のサブツリー ノードにアクセスして、左と右のサブツリーがあるかどうかが判断されます。

  1. ルート ノード (23) から開始して、curr は元のルート ノードを指し始めます。
    ここに画像の説明を挿入

  2. ルート ノード (23) を指す要素がスタックにプッシュされます (ルート ノードは後で処理されることが多いため、最初にスタックの一番下に置きます)。
    ここに画像の説明を挿入

  3. 現在のノードの左側のサブツリー ノード (34) を見つけます (curr=curr.left)。
    ここに画像の説明を挿入

  4. 現在移動されている curr (34 を指している) が空でない場合は、スタックにプッシュします。
    ここに画像の説明を挿入

  5. 現在のノードの左側の子ノードを探し続けます (34) (方法は前のノードと同じです。空でない場合はスタックにプッシュします)。
    ここに画像の説明を挿入
    ここに画像の説明を挿入

  6. 左のサブツリー ノードが空になるまで (つまり、図に示されている 77 に対応するノードの左のサブノードが空になる)、
    この時点で対応する最上位の要素を取得し、ノードに左のサブツリーがないことを示し、順序をトラバースします。順序に従って左と右の順、左 サブツリーは空であり、この時点でルート ノード要素を読み取る必要があります (つまり、スタックの対応する最上位要素が取り出されます)。ここで 77 は、最初に通過するノードです。順番に
    ここに画像の説明を挿入

  7. 77 を訪問すると、右側のサブツリー ノードに対応します。
    それが空の場合、このノードは右側のサブツリーに対応しないことを意味するため、対応する右側のノードにアクセスする必要はありません。これまでのところ、ルート ノードとして 77 を持つ左側のサブツリーは次のようになります
    ここに画像の説明を挿入
    。訪問されました

  8. 77 を左の子ノードとしてルート ノード 99 にアクセスします (スタックから対応するルート ノードを取得します。スタックの最上位要素は 99 です)。スタックの最上位要素にアクセスした後、すぐに右の
    サブツリーにアクセスする必要があります。
    ここに画像の説明を挿入

  9. 99 をルート ノードとして右のサブツリーにアクセスします。空でない場合は、右のサブツリーのルート ノードとしてスタックにプッシュします。
    ここに画像の説明を挿入

  10. 90 をルート ノードとする右サブツリーに左の子ノードがあるかどうかを問い合わせます。90 をルート
    ここに画像の説明を挿入
    ノードとする右のサブツリーに左の子ノードがある場合、方法は上記と同じです。
    左の子ノードがない場合は、次に、スタック ルート ノードの 90 を取り出します。
    ここに画像の説明を挿入

  11. 90をルートノードとするサブツリーに右側のサブツリーがあるかどうかを問い合わせます
    ここに画像の説明を挿入
    。このとき、90をルートノードとするサブツリーの右側のサブツリーノードは空であり、スタックに格納されている対応するルートノード要素にさらにアクセスします。

  12. スタックの最上位要素 (この時点では 34 に対応) の読み取りを続けます。この時点で
    ここに画像の説明を挿入
    、34 をルート ノードとして持つ左側のサブツリーの処理が終了し、ルート ノード 34 も読み込まれています。 34 に対応する右側のサブツリー。

  13. ルート ノードとして 34 を持つ右のサブツリーを読み取ります。
    ルート ノードとして 34 を持つ右のサブツリーは空であり、ルート ノードとして 34 を持つサブツリーが走査されています。スタック内の要素の処理を続けます
    ここに画像の説明を挿入

  14. スタック内の要素の読み取りを続けます (この時点では 23)。
    ここに画像の説明を挿入
    この時点で、バイナリ ツリー全体の左側のサブツリーが走査され、次に対応する右側のサブツリーが走査されます。

  15. 右のサブツリーのルート ノードをトラバースします (ルート ノード 23 は、右のサブツリーのルート ノードに対応しますが空ではありません。トラバースを続行し、最初に最初のルート ノード 21 をトラバースして、それをスタックにプッシュします)。
    ここに画像の説明を挿入
    ここに画像の説明を挿入

  16. 最初にルート ノードとして 21 を使用して左側のサブツリーのトラバースを続けます。空でない場合は、スタックへのプッシュを続けます (45)
    ここに画像の説明を挿入

  17. 空を指す左側のサブツリー
    (45 の左側の子ノード) が見つかるまで左に移動し続け、スタックの最上位要素の処理を開始し、スタックの最上位要素を読み取ります。
    ここに画像の説明を挿入
    ここに画像の説明を挿入

  18. ルート ノードとして 45 を持つ左側のサブツリーに右側の子ノードがあるかどうかを問い合わせます。
    ある場合は、それをスタックにプッシュします。次に左側の子ノードがあるかどうかを問い合わせます。
    ない場合は、ルート ノードとして 45 を持つサブツリーであることを意味します訪問されており、最上位要素の処理を続行します
    ここに画像の説明を挿入

  19. 21 をルート ノードとして右のサブツリーの状況を観察します。curr=curr.right の場合、
    ここに画像の説明を挿入
    右のサブツリーのルート ノードが空 (60) でない場合は、それをスタックにプッシュします。
    ここに画像の説明を挿入

  20. 60 をルート ノードとして右側のサブツリーに左右のノードがあるかどうかを確認します。
    左側の子ノードがある場合はトラバースを続行します。
    左側の子ノードがない場合は、最上位の要素 (60) を取り出してトラバースを開始します。右のサブツリー。
    右側の子ノードが空でない場合は、それをスタックにプッシュして走査を続行します。
    右側の子ノードが空でスタックも空の場合、順序どおりの走査全体が終了します。
    ここに画像の説明を挿入

2.2 コードの実装

コードの前の記述は Likou の内容を直接コピーしています. この関数の主な考え方は
ルート ノードからバイナリ ツリーをたどることです. ルート ノードが空の場合は空のリストを直接返します.
次は通常の処理(全体の処理は上記のトラバース処理と同じ)

  1. 2 つの新しいリストを作成します。1 つはスタックの最上位要素を格納するスタックとして、もう 1 つは最終的な走査結果を格納します。
  2. Curr はルート ノードを指し始めます
  3. トラバーサルの終了条件は、現在のポインタが空で、スタックに要素が存在しないことです (ここでは while ループ条件)。
  4. ルート ノードをスタックにプッシュし、ノード ポインタを左に移動します。
  5. 左シフト ノード ポインタが空の場合は、このノードをルート ノードとするサブツリーに左の子ノードがなく、走査順序が左、ルート、右、次に左が空で、順序どおりの走査が直接行われることを意味します。スタックの最上位要素 (ルート ノードの値) を読み取り、ポインタもルート ノードを指し、2 番目の while ループから抜け出します。
  6. 前のステップでルート ノードがサブツリーである右側の子ノードをクエリし、ポインタを移動して、上記の走査を繰り返し続けます (最初の while ループに入ります)。
  7. ポインターが空を指し、スタックに要素がなくなるまで、順序どおりの走査を終了します。

2.2.1 パイソン

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
    
        if not root:
            return []
        res, stack = list(), list()
        curr = root
        while curr or len(stack): # 指针为空且栈中元素为空时结束循环
            while curr: # 当前指针不为空,推入根节点
                stack.append(curr)
                curr = curr.left
            # 左子节点为空,则读取栈顶元素对应的根节点
            node = stack.pop()
            res.append(node.val)
            # 读取右子树
            curr = node.right
        return res

ここでの使用例は、
入力:[1,null,2,3]
出力:[1,3,2]
ここで、最初のルート ノードを出力します。
(TreeNode{val: 1, left: None, right: TreeNode{val: 2, left: TreeNode{val: 3, left: None, right: None}, right: None}}, 'root')
ここに画像の説明を挿入

2.2.2 JavaScript

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
    
    
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {
    
    TreeNode} root
 * @return {
    
    number[]}
 */
var inorderTraversal = function(root) {
    
    
    if (!root) return []
    const stack = [], res = []
    let curr = root
    let node
    while (!(!stack.length && !curr)) {
    
     // 指针为空且栈中无元素时,结束循环
    // while (stack.length || curr) {
    
    
        while (curr) {
    
     // 指针不为空
            stack.push(curr)
            curr = curr.left
        }
        node = stack.pop()
        res.push(node.val)
        curr = node.right
    }
    return res
};

3. 再帰的方法

3.1 トラバーサルプロセス

  1. バイナリ ツリーを分割する主なアイデア
    ここに画像の説明を挿入
    は、完全なバイナリ ツリーを左のサブツリー、ルート ノード、および右のサブツリーに分割し、
    ここに画像の説明を挿入
    さらに分割し続けることです。
    ここに画像の説明を挿入
    最も左のサブツリーに空の左の子ノードがある場合、再帰が終了します。

  2. さらに小さいサブツリーから順に訪問
    ここに画像の説明を挿入

  3. インオーダー
    ここに画像の説明を挿入
    トラバーサル = 左サブツリーのインオーダートラバーサル + ルートノード + 右サブツリーのインオーダートラバーサル

3.2 コードの実装

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
    
    
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {
    
    TreeNode} root
 * @return {
    
    number[]}
 */
var inorderTraversal = function(root) {
    
    
    if (!root) return []
    
    const inorder = (node, res) => {
    
    
        if (!node) return
        inorder(node.left, res)
        res.push(node.val)
        inorder(node.right, res)
    }

    const res = []
    inorder(root, res)
    return res
};

参考リンク

レッコの説明

おすすめ

転載: blog.csdn.net/m0_47146037/article/details/127259636