0 description du sujet
Lien vers le titre original Leetcode: Parcours dans l'ordre de l'arbre binaire
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
1 Algorithme récursif
Idées et algorithmes
Tout d'abord, nous devons comprendre ce qu'est la traversée dans l'ordre d'un arbre binaire: traversez cet arbre de la manière de visiter le sous-arbre gauche sous-arbre-racine nœud-droit, et lors de la visite du sous-arbre gauche ou du sous-arbre droit, nous suivons Parcourez de la même manière jusqu'à ce que l'arbre complet soit parcouru. Par conséquent, l'ensemble du processus de parcours est naturellement récursif, et nous pouvons directement simuler ce processus avec une fonction récursive.
La définition inorder (root) représente la réponse actuellement parcourue vers le nœud racine, puis selon la définition, il suffit d'appeler récursivement inorder (root.left) pour traverser le sous-arbre gauche du nœud racine, puis ajouter la valeur du nœud racine à la réponse, puis appeler de manière récursive inorder (root.right) Pour traverser le sous-arbre droit du nœud racine, la condition pour une terminaison récursive est de rencontrer un nœud vide.
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)
Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds d'arbre binaire. Dans le parcours de l'arbre binaire, chaque nœud sera visité une et une seule fois.
Complexité spatiale:O (n) O (n)O ( n ) . La complexité de l'espace dépend de la profondeur de la pile récursive, et la profondeur de la pile peut atteindreO (n) O (n)lorsque l'arbre binaire est une chaîneNiveau O ( n ) .
2 Algorithme itératif (pile)
Nous pouvons également implémenter des fonctions récursives de manière itérative. Les deux méthodes sont équivalentes. La différence est qu'une pile est implicitement maintenue pendant la récursivité, et nous devons simuler explicitement cette pile lors de l'itération.
# 其核心思想如下:
# 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
# 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
# 如果遇到的节点为灰色,则将节点的值输出。
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
White, Gray = 0, 1
res = []
stack = [(White,root)]
while stack:
color, node = stack.pop()
if not node: continue
if color == White:
stack.append((White,node.right))
stack.append((Gray,node))
stack.append((White,node.left))
else:
res.append(node.val)
return res
Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds d'arbre binaire. Dans le parcours de l'arbre binaire, chaque nœud sera visité une et une seule fois.
Complexité spatiale:O (n) O (n)O ( n ) . La complexité de l'espace dépend de la profondeur de la pile récursive, et la profondeur de la pile peut atteindreO (n) O (n)lorsque l'arbre binaire est une chaîneNiveau O ( n ) .
3 Traversée dans l'ordre de Morris
Idées et algorithmes
L'algorithme de parcours de Morris est une autre méthode de traversée d'arbres binaires, qui peut réduire la complexité spatiale de la traversée non récursive dans l'ordre vers O (1).
Morris traversal est une méthode de traversée d'espace constant, son essence est un arbre binaire fileté (Threaded Binary Tree), en fait, il utilise en fait n + 1 pointeurs vers NULL dans l'arbre binaire.
Pendant le processus de traversée, Morris traversal utilise le pointeur droit vide du nœud feuille pour pointer vers le nœud successeur de la traversée dans l'ordre, évitant ainsi la dépendance à la pile.
# (1)对于一个节点cur,找到它左子树的最右节点,看这个节点的right指针是null还是指向cur。
# (2)如果是null,说明左子树还没处理过,更新该指针为cur,然后进入左子树继续上述流程。
# (3)如果该指针已经是cur了,说明左子树已经处理完毕,现在是处理完毕后顺这最右节点的right指针回到该cur节点的,需先将该right指针恢复为null,处理该cur节点后进入右子树重复流程⑴。
class Solution:
def inorderTraversal(self, root: TreeNode) -> list:
node, res = root, []
while node:
if not node.left:
res.append(node.val)
node = node.right
else:
pre = node.left
while pre.right and pre.right != node:
pre = pre.right
if not pre.right:
pre.right = node
node = node.left
else:
pre.right = None
res.append(node.val)
node = node.right
return res
Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds dans l'arbre de recherche binaire. Dans le parcours de Morris, chaque nœud sera visité deux fois, donc la complexité temporelle totale estO (2 n) O (2n)O ( 2 n ) =O (n) O (n)O ( n ) .
Complexité spatiale:O (1) O (1)O ( 1 )。
référence
Notation des couleurs - une méthode générale et concise de traversée d'arbre
Morris traversal