递归可视化尝试(1)--CLI版:以计算二叉树的深度为例

后续会写其他版本(streamlit版/turtle版等等)
这个CLI版指用print来帮助理解

计算二叉树的深度python代码简洁版

  • 如下

    class Node:
        def __init__(self, value):
            self.value = value
            self.left = None
            self.right = None
    
    def max_depth(root):
        if not root:
            return 0
        left_depth = max_depth(root.left)
        right_depth = max_depth(root.right)
        return max(left_depth, right_depth) + 1
    
    # 示例用法
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    root.left.left.left = Node(6)
    
    print("二叉树的深度为:", max_depth(root))
    

print通俗易懂版!

帮助你从递归里绕出来~

"""
下面的例子树是:
         1
        / \
       2   3
      / \
     4   5
    /
   6
"""

class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None


def print_separator(char="-", length=50):
    """打印分隔符"""
    print(char * length)


def max_depth(root, parent=None, direction=None):
    if not root:
        if parent:
            print_separator("=")
            print(f"max_depth(None)开始递归,此为节点{parent.value}{direction}子树")
        else:
            print_separator("=")
            print("max_depth(None)开始递归")
        print("max_depth(None)结束,返回值为:0")
        print_separator("=")
        return 0

    if parent:
        print_separator()
        print(f"从节点{parent.value}进入其{direction}子节点{root.value}")
    print_separator("=")
    print(f"max_depth({root.value})开始递归")

    left_depth = max_depth(root.left, root, "左")
    right_depth = max_depth(root.right, root, "右")
    print(f"节点{root.value}的左子树深度为:{left_depth}")
    print(f"节点{root.value}的右子树深度为:{right_depth}")
    result = max(left_depth, right_depth) + 1
    print(f"取其最大值,所以节点{root.value}的深度为:{result}")
    print(f"max_depth({root.value})结束,返回值为:{result}")
    if parent:
        print(f"从节点{root.value}返回节点{parent.value},继续调用max_depth")
    print_separator("=")
    return result


# 示例用法
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
root.left.left.left = Node(6)

print("计算二叉树深度:")
print_separator("*", 60)
print("二叉树的深度为:", max_depth(root))
print_separator("*", 60)


可视化效果


计算二叉树深度:
************************************************************
==================================================
max_depth(1)开始递归
--------------------------------------------------
从节点1进入其左子节点2
==================================================
max_depth(2)开始递归
--------------------------------------------------
从节点2进入其左子节点4
==================================================
max_depth(4)开始递归
--------------------------------------------------
从节点4进入其左子节点6
==================================================
max_depth(6)开始递归
==================================================
max_depth(None)开始递归,此为节点6的左子树
max_depth(None)结束,返回值为:0
==================================================
==================================================
max_depth(None)开始递归,此为节点6的右子树
max_depth(None)结束,返回值为:0
==================================================
节点6的左子树深度为:0
节点6的右子树深度为:0
取其最大值,所以节点6的深度为:1
max_depth(6)结束,返回值为:1
从节点6返回节点4,继续调用max_depth
==================================================
==================================================
max_depth(None)开始递归,此为节点4的右子树
max_depth(None)结束,返回值为:0
==================================================
节点4的左子树深度为:1
节点4的右子树深度为:0
取其最大值,所以节点4的深度为:2
max_depth(4)结束,返回值为:2
从节点4返回节点2,继续调用max_depth
==================================================
--------------------------------------------------
从节点2进入其右子节点5
==================================================
max_depth(5)开始递归
==================================================
max_depth(None)开始递归,此为节点5的左子树
max_depth(None)结束,返回值为:0
==================================================
==================================================
max_depth(None)开始递归,此为节点5的右子树
max_depth(None)结束,返回值为:0
==================================================
节点5的左子树深度为:0
节点5的右子树深度为:0
取其最大值,所以节点5的深度为:1
max_depth(5)结束,返回值为:1
从节点5返回节点2,继续调用max_depth
==================================================
节点2的左子树深度为:2
节点2的右子树深度为:1
取其最大值,所以节点2的深度为:3
max_depth(2)结束,返回值为:3
从节点2返回节点1,继续调用max_depth
==================================================
--------------------------------------------------
从节点1进入其右子节点3
==================================================
max_depth(3)开始递归
==================================================
max_depth(None)开始递归,此为节点3的左子树
max_depth(None)结束,返回值为:0
==================================================
==================================================
max_depth(None)开始递归,此为节点3的右子树
max_depth(None)结束,返回值为:0
==================================================
节点3的左子树深度为:0
节点3的右子树深度为:0
取其最大值,所以节点3的深度为:1
max_depth(3)结束,返回值为:1
从节点3返回节点1,继续调用max_depth
==================================================
节点1的左子树深度为:3
节点1的右子树深度为:1
取其最大值,所以节点1的深度为:4
max_depth(1)结束,返回值为:4
==================================================
二叉树的深度为: 4
************************************************************

添加的这些print语句分别是基于何种动机?

1.开始/结束递归的打印语句:

print(f"max_depth({root.value})开始递归")print(f"max_depth({root.value})结束,返回值为:{result}")
这两条语句用于标记每次递归调用的开始和结束。这有助于我们跟踪函数何时开始处理一个新的节点以及何时完成处理。

2.递归终止条件的打印语句:

当函数递归到一个空节点时,输出"max_depth(None)开始递归"。这让我们可以看到函数如何处理叶节点(叶节点没有子节点,或者是叶节点的子节点是空的)

3.打印当前节点的左/右子树深度:

print(f"节点{root.value}的左子树深度为:{left_depth}")print(f"节点{root.value}的右子树深度为:{right_depth}")
这两条语句可以显示一个节点的左右子树的深度。有助于我们理解某个节点的深度(max(左,右)+1)

4.显示计算结果:

print(f"取其最大值,所以节点{root.value}的深度为:{result}") 显示当前节点的深度。
我们知道节点的深度是其左右子树深度的最大值加1,这个打印语句就是为了验证这一点。

5.递归导航的打印语句:

print(f"从节点{parent.value}进入其{direction}子节点{root.value}")print(f"从节点{root.value}返回节点{parent.value},继续调用max_depth")
这两条语句帮助我们跟踪函数在递归树中的导航路径。当函数从一个节点跳转到其子节点或返回到父节点时,这些语句都会输出。

6.分隔符的打印语句:

print_separator("=") 这个函数调用打印一个分隔线,使输出更加有条理。

你可能感兴趣的:(数据结构与算法,算法)