{"id":"recursion-examples-binary-trees","slug":"binary-trees","title":"Binary trees","text":"A list is a row: after each item comes one next item, and a loop walks along the row from the start to the end. Plenty of data isn't a row. A family tree, the folders on a computer and a tournament bracket all branch: one thing leads to two or more, and each of those leads on to more again. The simplest data that branches is a **binary tree**:\n\n```text\n        8\n       / \\\n      3   10\n     / \\    \\\n    1   6    14\n```\n\nEach value in it sits in a **node**. A node has a value and at most two **children**, a left one and a right one. The **root** is the node at the top, the one that all the others hang from, and the nodes without children are **leaves**: here 1, 6 and 14.\n\nA tree needs only one class, for a node that knows its value and its two children. A missing child is `None`:\n\n```python\nclass Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n```\n\nSince the children are parameters with default values, the whole tree above can be built by nesting the calls of the constructor:\n\n```python\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\n```\n\n### A tree made of trees\n\nLook at the left child of the root in that line: `Node(3, Node(1), Node(6))`. It's built in just the same way as the whole tree, only smaller. Any node, together with everything below it, is a tree in its own right, a **subtree**. So a question about a tree can be answered by asking the same question about its two subtrees and adding what the node at the top brings. That's a recursive function, and the empty tree, `None`, makes a handy base case.\n\nCounting the nodes shows how. An empty tree has 0 nodes. Any other tree has its root, which is 1 node, plus the nodes of its left subtree, plus the nodes of its right subtree:\n\n```python\nclass Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef count_nodes(node):\n    if node is None:\n        return 0\n    return 1 + count_nodes(node.left) + count_nodes(node.right)\n\n\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nprint(count_nodes(tree))\nprint(count_nodes(tree.left))\n```\n\n```output\n6\n3\n```\n\n`count_nodes(tree.left)` counts only the subtree of 3, 1 and 6. The calls stop at the leaves: a leaf's `left` and `right` are both `None`, and a call that gets `None` returns 0 straight away.\n\nWithout the check for `None`, the calls run into the missing children of the leaves:\n\n```python\nclass Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef count_nodes(node):\n    return 1 + count_nodes(node.left) + count_nodes(node.right)\n\n\nprint(count_nodes(Node(5)))\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 12, in <module>\n    print(count_nodes(Node(5)))\n          ~~~~~~~~~~~^^^^^^^^^\n  File \"main.py\", line 9, in count_nodes\n    return 1 + count_nodes(node.left) + count_nodes(node.right)\n               ~~~~~~~~~~~^^^^^^^^^^^\n  File \"main.py\", line 9, in count_nodes\n    return 1 + count_nodes(node.left) + count_nodes(node.right)\n                           ^^^^^^^^^\nAttributeError: 'NoneType' object has no attribute 'left'\n```\n\nThe leaf's `left` is `None`, and `None` has no attributes. Whenever you see `'NoneType' object has no attribute`, look for a missing check for `None`.\n\n### Printing every value\n\nA function that prints the values has the same shape. It has nothing to return, so for an empty tree it simply returns, and for any other tree it prints the node's value and then hands each subtree to a call of its own:\n\n```python\nclass Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef print_values(node):\n    if node is None:\n        return\n    print(node.value)\n    print_values(node.left)\n    print_values(node.right)\n\n\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nprint_values(tree)\n```\n\n```output\n8\n3\n1\n6\n10\n14\n```\n\nFollow the calls. The call for the root prints 8 and then calls the function for the subtree of 3. That call prints 3 and calls the function for 1, which prints 1 and finds `None` on both sides. Next the call for 3 deals with 6. Only when the subtree of 3 is done does the call for the root get to its last line and move on to 10. Where the `print` stands decides the order: here it comes before the two calls, so every node is printed before the nodes below it.\n","task":"The function prints a tree as an outline, each value indented by two spaces per level. Fill in the blank so the left subtree is printed one level deeper. The program should print:\n\n```\n8\n  3\n    1\n    6\n  10\n    14\n```\n","kind":"fill","seed":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef show(node, depth):\n    if node is None:\n        return\n    print(\"  \" * depth + str(node.value))\n    show(node.left, [[depth + 1]])\n    show(node.right, depth + 1)\n\n\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nshow(tree, 0)\n","solution":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef show(node, depth):\n    if node is None:\n        return\n    print(\"  \" * depth + str(node.value))\n    show(node.left, depth + 1)\n    show(node.right, depth + 1)\n\n\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nshow(tree, 0)\n","hints":["The children are one level deeper than the node itself.","The left subtree gets the same depth as the right one: `depth + 1`."],"tests":[{"name":"Output","stdin":"","expect":"8\n  3\n    1\n    6\n  10\n    14","hidden":false}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef visit(node):\n    if node is not None:\n        visit(node.left)\n        visit(node.right)\n        print(node.value)\n\n\nvisit(Node(1, Node(2), Node(3, Node(4))))\n","solution":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef visit(node):\n    if node is not None:\n        visit(node.left)\n        visit(node.right)\n        print(node.value)\n\n\nvisit(Node(1, Node(2), Node(3, Node(4))))\n","hints":["Draw the tree first: 1 is the root, 2 its left child and 3 its right child, and 4 is the left child of 3.","This time a node prints its value only after both of its subtrees have been visited.","So 2 prints first. In the right subtree, 4 prints before 3, and the root comes last."],"tests":[{"name":"Output","stdin":"","expect":"2\n4\n3\n1","hidden":false}],"require":[],"forbid":[],"lines":["2","4","3","1"]},{"task":"A leaf is a node without children. Write a recursive function `count_leaves(node)` that returns the number of leaves in a tree. An empty tree, `None`, has no leaves.\n\nFor example, this program:\n\n```python\ntree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nprint(count_leaves(tree))\n```\n\nprints:\n\n```\n3\n```\n","kind":"code","seed":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef count_leaves(node):\n    pass\n\n\nif __name__ == \"__main__\":\n    tree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\n    print(count_leaves(tree))\n","solution":"class Node:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\n\ndef count_leaves(node):\n    if node is None:\n        return 0\n    if node.left is None and node.right is None:\n        return 1\n    return count_leaves(node.left) + count_leaves(node.right)\n\n\nif __name__ == \"__main__\":\n    tree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\n    print(count_leaves(tree))\n","hints":["There are two base cases: an empty tree has 0 leaves, and a node whose children are both `None` is a leaf, 1.","Any other node isn't a leaf itself, so its leaves are the leaves of its left subtree plus those of its right subtree.","`return count_leaves(node.left) + count_leaves(node.right)`"],"tests":[{"name":"Test 1","stdin":"","call":"tree = Node(8, Node(3, Node(1), Node(6)), Node(10, None, Node(14)))\nprint(count_leaves(tree))\n","expect":"3","hidden":false},{"name":"count_leaves(Node(5))","stdin":"","call":"count_leaves(Node(5))\n","expect":"1","hidden":true,"returns":true},{"name":"count_leaves(None)","stdin":"","call":"count_leaves(None)\n","expect":"0","hidden":true,"returns":true},{"name":"count_leaves(Node(1, Node(2, Node(3))))","stdin":"","call":"count_leaves(Node(1, Node(2, Node(3))))\n","expect":"1","hidden":true,"returns":true},{"name":"count_leaves(Node(1, Node(2, Node(4), Node(5)), Node(3, Node(6), Node(7))))","stdin":"","call":"count_leaves(Node(1, Node(2, Node(4), Node(5)), Node(3, Node(6), Node(7))))\n","expect":"4","hidden":true,"returns":true}],"require":[{"pattern":"def count_leaves\\b[^\\n]*\\n(?:[ \\t]*\\n|[ \\t]+[^\\n]*\\n)*?[ \\t]+[^\\n]*\\bcount_leaves\\s*\\(","message":"Make `count_leaves` call itself inside its own body."}],"forbid":[]}]}