C++ 二叉树

看到关于二叉树的问题,首先要想到关于二叉树的一些常见遍历方式,
对于二叉树的遍历有

前序遍历
中序遍历
后续遍历
深度优先搜索(DFS)
宽度优先搜索(BFS)
除了上面介绍的5种以外,还有Morris(莫里斯)的前中后3种遍历方式,总共也就这8种。所以只要遇到二叉树相关的算法题,首先想到的就是上面的几种遍历方式,然后再稍加修改,基本上也就这个套路。

这题让求的就是让把二叉树中每行都串联起来,对于这道题来说最适合的就是BFS。也就是一行一行的遍历,遍历的时候顺便把他们给串起来,如下图所示

def _build_tree_string(root, curr_index, include_index, delimiter):
    if root is None: return [], 0, 0, 0
    line1, line2 = [], []
    if include_index:
        node_repr = "{}{}{}".format(curr_index, delimiter, root.val)
    else:
        node_repr = str(root.val)

    new_root_width = gap_size = len(node_repr)

    # Get the left and right sub-boxes, their widths, and root repr positions
    l_box, l_box_width, l_root_start, l_root_end = _build_tree_string(
        root.left, 2 * curr_index + 1, include_index, delimiter)
    r_box, r_box_width, r_root_start, r_root_end = _build_tree_string(
        root.right, 2 * curr_index + 2, include_index, delimiter)

    # Draw the branch connecting the current root node to the left sub-box
    # Pad the line with whitespaces where necessary
    if l_box_width > 0:
        l_root = (l_root_start + l_root_end) // 2 + 1
        line1.append(" " * (l_root + 1))
        line1.append("_" * (l_box_width - l_root))
        line2.append(" " * l_root + "/")
        line2.append(" " * (l_box_width - l_root))
        new_root_start = l_box_width + 1
        gap_size += 1
    else:
        new_root_start = 0

    # Draw the representation of the current root node
    line1.append(node_repr)
    line2.append(" " * new_root_width)

    # Draw the branch connecting the current root node to the right sub-box
    # Pad the line with whitespaces where necessary
    if r_box_width > 0:
        r_root = (r_root_start + r_root_end) // 2
        line1.append("_" * r_root)
        line1.append(" " * (r_box_width - r_root + 1))
        line2.append(" " * r_root + "\\")
        line2.append(" " * (r_box_width - r_root))
        gap_size += 1
    new_root_end = new_root_start + new_root_width - 1

    # Combine the left and right sub-boxes with the branches drawn above
    gap = " " * gap_size
    new_box = ["".join(line1), "".join(line2)]
    for i in range(max(len(l_box), len(r_box))):
        l_line = l_box[i] if i < len(l_box) else " " * l_box_width
        r_line = r_box[i] if i < len(r_box) else " " * r_box_width
        new_box.append(l_line + gap + r_line)

    return new_box, len(new_box[0]), new_root_start, new_root_end


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

    def __str__(self) -> str:
        lines = _build_tree_string(self, 0, False, "-")[0]
        return "\n" + "\n".join((line.rstrip() for line in lines))


from typing import List, Optional, Tuple


class BTree():
    def __init__(self, root=None):
        self.root = root
        self.depth = 0

    def add(self, item):
        node = TreeNode(item)
        if self.root is None:
            self.root = node
            return
        else:
            queue = []
            queue.append(self.root)
            while queue:
                cur_node = queue.pop(0)
                if cur_node.left is None:
                    cur_node.left = node
                    return
                elif cur_node.right is None:
                    cur_node.right = node
                    return
                else:
                    queue.append(cur_node.left)
                    queue.append(cur_node.right)

    # 先访问根节点,然后遍历左子树,最后遍历右子树。
    def preorderTraversal(self, root):
        if not root: return []
        res = []

        # recursion
        def preorder(root):
            if not root: return
            res.append(root.val)
            preorder(root.left)
            preorder(root.right)

        preorder(root)

        # Iteration1
        # stack = []
        # cur = root
        # while stack or cur:
        #     while cur:
        #         res.append(cur.val)
        #         stack.append(cur)
        #         cur = cur.left
        #     cur = stack.pop()
        #     cur = cur.right

        # # Iteration2
        # stack = [root]
        # while(stack):
        #     cur = stack.pop()
        #     res.append(cur.val)
        #     if cur.right:
        #         stack.append(cur.right)
        #     if cur.left:
        #         stack.append(cur.left)
        return res

    # 先遍历左子树,然后访问根节点,然后遍历右子树。
    def inorderTraversal(self, root):
        if not root: return []
        res = []

        # recursion
        def inorder(root):
            if not root: return
            inorder(root.left)
            res.append(root.val)
            inorder(root.right)

        inorder(root)

        # Iteration1
        # stack = []
        # cur = root
        # while stack or cur:
        #     while cur:
        #         stack.append(cur)
        #         cur = cur.left
        #     cur = stack.pop()
        #     res.append(cur.val)
        #     cur = cur.right

        # # Iteration2
        # stack = [root]
        # while(stack):
        #     cur = stack.pop()
        #     res.append(cur.val)
        #     if cur.right:
        #         stack.append(cur.right)
        #     if cur.left:
        #         stack.append(cur.left)
        return res

    # 先遍历左子树,然后遍历右子树,最后访问树的根节点。
    def poseorderTraversal(self, root):
        if not root: return []
        res = []

        # recursion
        def poseorder(root):
            if not root: return
            poseorder(root.left)
            poseorder(root.right)
            res.append(root.val)

        poseorder(root)
        # Iteration1
        # stack = []
        # cur = root
        # while stack or cur:
        #     while cur:
        #         res.append(cur.val)
        #         stack.append(cur)
        #         cur = cur.right
        #     cur = stack.pop()
        #     cur = cur.left
        # res = res[::-1]
        # # Iteration2
        # stack = [root]
        # while(stack):
        #     cur = stack.pop()
        #     res.append(cur.val)
        #     if cur.left: stack.append(cur.left)
        #     if cur.right: stack.append(cur.right)
        # res = res[::-1]
        return res

    # BFS
    def levelorderTraversal(self, root):
        if not root:
            return []
        queue, res = [root], []
        while (queue):
            # cur = queue.pop(0)
            # res.append(cur.val)
            # if cur.left: queue.append(cur.left)
            # if cur.right: queue.append(cur.right)
            # 显示层数
            res.append([node.val for node in queue])
            res.append(['*'])
            size = len(queue)
            for i in range(size):
                cur = queue.pop(0)
                if cur.left: queue.append(cur.left)
                if cur.right: queue.append(cur.right)
        return res

    def maximum_depth(self, root):
        if not root: return 0

        def max_depth(cur, depth):
            if not cur: return
            if (not cur.left and not cur.right):
                if self.depth < depth:
                    self.depth = depth
            max_depth(cur.left, depth + 1)
            max_depth(cur.right, depth + 1)

        max_depth(root, 1)
        return self.depth

    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        """
        :param preorder: [3,9,20,15,77] 根 左 右
        :param inorder: [9,3,15,20,7] 左 根 右
        :param postorder: [9,15,7,20,3] 左 右 根
        :return:
        """

        def build(in_left, in_right):
            if in_left > in_right: return None

            # 选择 pre_idx 位置的元素作为当前子树根节点
            val = preorder.pop(0)
            root = TreeNode(val)

            # 根据 root 所在位置分成左右两棵子树
            index = idx_map[val]

            # 构造左子树
            root.left = build(in_left, index - 1)
            # 构造右子树
            root.right = build(index + 1, in_right)
            return root

            # 建立(元素,下标)键值对的哈希表

        idx_map = {val: idx for idx, val in enumerate(inorder)}

        return build(0, len(inorder) - 1)


tree0 = TreeNode(2)
tree0.left = TreeNode(1)
tree0.left.left = TreeNode(0)
tree0.left.right = TreeNode(2)
tree0.right = TreeNode(3)
tree0.right.left = TreeNode(2)
tree0.right.right = TreeNode(4)

BT = BTree()
tree0 = BT.buildTree([2, 1, 0, 4, 3, -1, 5], [0, 1, 4, 2, -1, 3, 5])
print(tree0)
result0 = BT.preorderTraversal(tree0)
print("前序遍历(根->左->右)", result0)
result1 = BT.inorderTraversal(tree0)
print("中序遍历(左->根->右)", result1)
result2 = BT.poseorderTraversal(tree0)
print("后序遍历(左->右->根)", result2)
result2 = BT.levelorderTraversal(tree0)
print("层序遍历 ", result2)
result3 = BT.maximum_depth(tree0)
print(result3)
exit()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值