From 5deffe956d01b3b20958c15b749464380483432e Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Sat, 23 Oct 2021 09:27:24 -0300 Subject: [PATCH 01/10] [mypy] Fix type annotations for binary tree traversals in data structures --- .../binary_tree/binary_tree_traversals.py | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index de9e9d60d272..5e9f4c935840 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -2,20 +2,24 @@ from __future__ import annotations from dataclasses import dataclass +from typing import Optional, Sequence @dataclass class Node: data: int - left: Node | None = None - right: Node | None = None + left: NodeType = None + right: NodeType = None + + +NodeType = Optional[Node] def make_tree() -> Node: return Node(1, Node(2, Node(4), Node(5)), Node(3)) -def preorder(root: Node): +def preorder(root: NodeType) -> list[int]: """ Pre-order traversal visits root node, left subtree, right subtree. >>> preorder(make_tree()) @@ -24,7 +28,7 @@ def preorder(root: Node): return [root.data] + preorder(root.left) + preorder(root.right) if root else [] -def postorder(root: Node): +def postorder(root: NodeType) -> list[int]: """ Post-order traversal visits left subtree, right subtree, root node. >>> postorder(make_tree()) @@ -33,7 +37,7 @@ def postorder(root: Node): return postorder(root.left) + postorder(root.right) + [root.data] if root else [] -def inorder(root: Node): +def inorder(root: NodeType) -> list[int]: """ In-order traversal visits left subtree, root node, right subtree. >>> inorder(make_tree()) @@ -42,7 +46,7 @@ def inorder(root: Node): return inorder(root.left) + [root.data] + inorder(root.right) if root else [] -def height(root: Node): +def height(root: NodeType) -> int: """ Recursive function for calculating the height of the binary tree. >>> height(None) @@ -53,31 +57,31 @@ def height(root: Node): return (max(height(root.left), height(root.right)) + 1) if root else 0 -def level_order_1(root: Node): +def level_order_1(root: NodeType) -> Sequence[NodeType]: """ Print whole binary tree in Level Order Traverse. Level Order traverse: Visit nodes of the tree level-by-level. """ if not root: - return + return [] temp = root - que = [temp] - while len(que) > 0: - print(que[0].data, end=" ") - temp = que.pop(0) + queue = [temp] + while queue: + print(queue[0].data, end=" ") + temp = queue.pop(0) if temp.left: - que.append(temp.left) + queue.append(temp.left) if temp.right: - que.append(temp.right) - return que + queue.append(temp.right) + return queue -def level_order_2(root: Node, level: int): +def level_order_2(root: NodeType, level: int) -> None: """ Level-wise traversal: Print all nodes present at the given level of the binary tree """ if not root: - return root + return if level == 1: print(root.data, end=" ") elif level > 1: @@ -85,7 +89,7 @@ def level_order_2(root: Node, level: int): level_order_2(root.right, level - 1) -def print_left_to_right(root: Node, level: int): +def print_left_to_right(root: NodeType, level: int) -> None: """ Print elements on particular level from left to right direction of the binary tree. """ @@ -98,7 +102,7 @@ def print_left_to_right(root: Node, level: int): print_left_to_right(root.right, level - 1) -def print_right_to_left(root: Node, level: int): +def print_right_to_left(root: NodeType, level: int) -> None: """ Print elements on particular level from right to left direction of the binary tree. """ @@ -111,7 +115,7 @@ def print_right_to_left(root: Node, level: int): print_right_to_left(root.left, level - 1) -def zigzag(root: Node): +def zigzag(root: NodeType) -> None: """ ZigZag traverse: Print node left to right and right to left, alternatively. """ @@ -126,7 +130,7 @@ def zigzag(root: Node): flag = 0 -def main(): # Main function for testing. +def main() -> None: # Main function for testing. """ Create binary tree. """ From 544b3fc83f3d5e3665bd11f67c7ec739571bef12 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 13:41:09 -0300 Subject: [PATCH 02/10] Change variable name and update level_order_1 to use a deque Using a deque instead of a list here, because since we are removing from the beginning of the list, the deque will be more efficient. --- .../binary_tree/binary_tree_traversals.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 5e9f4c935840..05604374cdf7 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -2,6 +2,7 @@ from __future__ import annotations from dataclasses import dataclass +from collections import deque from typing import Optional, Sequence @@ -64,16 +65,19 @@ def level_order_1(root: NodeType) -> Sequence[NodeType]: """ if not root: return [] + temp = root - queue = [temp] - while queue: - print(queue[0].data, end=" ") - temp = queue.pop(0) + process_queue = deque([temp]) + + while process_queue: + print(process_queue[0].data, end=" ") + temp = process_queue.popleft() + if temp.left: - queue.append(temp.left) + process_queue.append(temp.left) if temp.right: - queue.append(temp.right) - return queue + process_queue.append(temp.right) + return process_queue def level_order_2(root: NodeType, level: int) -> None: From f136983f1b3c4c1acb8e235846a1e36b14105bfd Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 14:10:04 -0300 Subject: [PATCH 03/10] remove duplicate function --- .../binary_tree/binary_tree_traversals.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 05604374cdf7..b7d98e0ddb5b 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -1,8 +1,8 @@ # https://en.wikipedia.org/wiki/Tree_traversal from __future__ import annotations -from dataclasses import dataclass from collections import deque +from dataclasses import dataclass from typing import Optional, Sequence @@ -80,19 +80,6 @@ def level_order_1(root: NodeType) -> Sequence[NodeType]: return process_queue -def level_order_2(root: NodeType, level: int) -> None: - """ - Level-wise traversal: Print all nodes present at the given level of the binary tree - """ - if not root: - return - if level == 1: - print(root.data, end=" ") - elif level > 1: - level_order_2(root.left, level - 1) - level_order_2(root.right, level - 1) - - def print_left_to_right(root: NodeType, level: int) -> None: """ Print elements on particular level from left to right direction of the binary tree. @@ -150,7 +137,7 @@ def main() -> None: # Main function for testing. level_order_1(root) print("\nLevel-wise order Traversal is : ") for h in range(1, height(root) + 1): - level_order_2(root, h) + print_left_to_right(root, h) print("\nZigZag order Traversal is : ") zigzag(root) print() From 705689ebee9991342e26a193d9916ffc1d74c494 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 14:16:49 -0300 Subject: [PATCH 04/10] Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law --- data_structures/binary_tree/binary_tree_traversals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index b7d98e0ddb5b..f6b1c6f7275e 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -58,7 +58,7 @@ def height(root: NodeType) -> int: return (max(height(root.left), height(root.right)) + 1) if root else 0 -def level_order_1(root: NodeType) -> Sequence[NodeType]: +def level_order(root: NodeType) -> Sequence[NodeType]: """ Print whole binary tree in Level Order Traverse. Level Order traverse: Visit nodes of the tree level-by-level. From c142683f7ced80b4f3e490e6d07ec2baacee7ac8 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 14:36:31 -0300 Subject: [PATCH 05/10] fix function name at line 137 --- data_structures/binary_tree/binary_tree_traversals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index f6b1c6f7275e..bbb245400376 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -134,7 +134,7 @@ def main() -> None: # Main function for testing. print(f"Post-order Traversal is {postorder(root)}") print(f"Height of Tree is {height(root)}") print("Complete Level Order Traversal is : ") - level_order_1(root) + level_order(root) print("\nLevel-wise order Traversal is : ") for h in range(1, height(root) + 1): print_left_to_right(root, h) From 129f823a57b6500745e1a29caa6afec0507bb34a Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 14:48:42 -0300 Subject: [PATCH 06/10] Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law --- data_structures/binary_tree/binary_tree_traversals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index bbb245400376..986ba4bc8f22 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -3,7 +3,7 @@ from collections import deque from dataclasses import dataclass -from typing import Optional, Sequence +from typing import Sequence @dataclass From e8fb8c0317898affe0059f699fa756228245a2c1 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 26 Oct 2021 14:48:48 -0300 Subject: [PATCH 07/10] Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law --- data_structures/binary_tree/binary_tree_traversals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 986ba4bc8f22..e2ab68141632 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -13,7 +13,7 @@ class Node: right: NodeType = None -NodeType = Optional[Node] +NodeType = Node | None def make_tree() -> Node: From bd3c04a9302d756b754195075f4709a952f45166 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Wed, 27 Oct 2021 10:37:41 -0300 Subject: [PATCH 08/10] Remove type alias and use the new syntax --- .../binary_tree/binary_tree_traversals.py | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index e2ab68141632..07dd5b79b752 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -9,18 +9,15 @@ @dataclass class Node: data: int - left: NodeType = None - right: NodeType = None + left: Node | None = None + right: Node | None = None -NodeType = Node | None - - -def make_tree() -> Node: +def make_tree() -> Node | None: return Node(1, Node(2, Node(4), Node(5)), Node(3)) -def preorder(root: NodeType) -> list[int]: +def preorder(root: Node | None) -> list[int]: """ Pre-order traversal visits root node, left subtree, right subtree. >>> preorder(make_tree()) @@ -29,7 +26,7 @@ def preorder(root: NodeType) -> list[int]: return [root.data] + preorder(root.left) + preorder(root.right) if root else [] -def postorder(root: NodeType) -> list[int]: +def postorder(root: Node | None) -> list[int]: """ Post-order traversal visits left subtree, right subtree, root node. >>> postorder(make_tree()) @@ -38,7 +35,7 @@ def postorder(root: NodeType) -> list[int]: return postorder(root.left) + postorder(root.right) + [root.data] if root else [] -def inorder(root: NodeType) -> list[int]: +def inorder(root: Node | None) -> list[int]: """ In-order traversal visits left subtree, root node, right subtree. >>> inorder(make_tree()) @@ -47,7 +44,7 @@ def inorder(root: NodeType) -> list[int]: return inorder(root.left) + [root.data] + inorder(root.right) if root else [] -def height(root: NodeType) -> int: +def height(root: Node | None) -> int: """ Recursive function for calculating the height of the binary tree. >>> height(None) @@ -58,7 +55,7 @@ def height(root: NodeType) -> int: return (max(height(root.left), height(root.right)) + 1) if root else 0 -def level_order(root: NodeType) -> Sequence[NodeType]: +def level_order(root: Node | None) -> Sequence[Node | None]: """ Print whole binary tree in Level Order Traverse. Level Order traverse: Visit nodes of the tree level-by-level. @@ -80,7 +77,7 @@ def level_order(root: NodeType) -> Sequence[NodeType]: return process_queue -def print_left_to_right(root: NodeType, level: int) -> None: +def print_left_to_right(root: Node | None, level: int) -> None: """ Print elements on particular level from left to right direction of the binary tree. """ @@ -93,7 +90,7 @@ def print_left_to_right(root: NodeType, level: int) -> None: print_left_to_right(root.right, level - 1) -def print_right_to_left(root: NodeType, level: int) -> None: +def print_right_to_left(root: Node | None, level: int) -> None: """ Print elements on particular level from right to left direction of the binary tree. """ @@ -106,7 +103,7 @@ def print_right_to_left(root: NodeType, level: int) -> None: print_right_to_left(root.left, level - 1) -def zigzag(root: NodeType) -> None: +def zigzag(root: Node | None) -> None: """ ZigZag traverse: Print node left to right and right to left, alternatively. """ From 3ad72ec4997d1c7b1d9c38cba6c026deb311759b Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Wed, 27 Oct 2021 10:42:09 -0300 Subject: [PATCH 09/10] Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law --- data_structures/binary_tree/binary_tree_traversals.py | 1 - 1 file changed, 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 07dd5b79b752..5e87760707b0 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -67,7 +67,6 @@ def level_order(root: Node | None) -> Sequence[Node | None]: process_queue = deque([temp]) while process_queue: - print(process_queue[0].data, end=" ") temp = process_queue.popleft() if temp.left: From 90d2e387734686e7701629443bd2766dc6c5d52f Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Wed, 27 Oct 2021 11:42:05 -0300 Subject: [PATCH 10/10] Remove prints inside functions and return lists --- .../binary_tree/binary_tree_traversals.py | 129 +++++++++++------- 1 file changed, 82 insertions(+), 47 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 5e87760707b0..9a62393914da 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -3,7 +3,7 @@ from collections import deque from dataclasses import dataclass -from typing import Sequence +from typing import Any, Sequence @dataclass @@ -57,65 +57,95 @@ def height(root: Node | None) -> int: def level_order(root: Node | None) -> Sequence[Node | None]: """ - Print whole binary tree in Level Order Traverse. + Returns a list of nodes value from a whole binary tree in Level Order Traverse. Level Order traverse: Visit nodes of the tree level-by-level. """ - if not root: - return [] + output: list[Any] = [] + + if root is None: + return output - temp = root - process_queue = deque([temp]) + process_queue = deque([root]) while process_queue: - temp = process_queue.popleft() + node = process_queue.popleft() + output.append(node.data) - if temp.left: - process_queue.append(temp.left) - if temp.right: - process_queue.append(temp.right) - return process_queue + if node.left: + process_queue.append(node.left) + if node.right: + process_queue.append(node.right) + return output -def print_left_to_right(root: Node | None, level: int) -> None: +def get_nodes_from_left_to_right( + root: Node | None, level: int +) -> Sequence[Node | None]: """ - Print elements on particular level from left to right direction of the binary tree. + Returns a list of nodes value from a particular level: + Left to right direction of the binary tree. """ - if not root: - return - if level == 1: - print(root.data, end=" ") - elif level > 1: - print_left_to_right(root.left, level - 1) - print_left_to_right(root.right, level - 1) + output: list[Any] = [] + + def populate_output(root: Node | None, level: int) -> None: + if not root: + return + if level == 1: + + output.append(root.data) + elif level > 1: + populate_output(root.left, level - 1) + populate_output(root.right, level - 1) + + populate_output(root, level) + return output -def print_right_to_left(root: Node | None, level: int) -> None: +def get_nodes_from_right_to_left( + root: Node | None, level: int +) -> Sequence[Node | None]: """ - Print elements on particular level from right to left direction of the binary tree. + Returns a list of nodes value from a particular level: + Right to left direction of the binary tree. """ - if not root: - return - if level == 1: - print(root.data, end=" ") - elif level > 1: - print_right_to_left(root.right, level - 1) - print_right_to_left(root.left, level - 1) + output: list[Any] = [] + def populate_output(root: Node | None, level: int) -> None: + if root is None: + return + if level == 1: + output.append(root.data) + elif level > 1: + populate_output(root.right, level - 1) + populate_output(root.left, level - 1) -def zigzag(root: Node | None) -> None: + populate_output(root, level) + return output + + +def zigzag(root: Node | None) -> Sequence[Node | None] | list[Any]: """ - ZigZag traverse: Print node left to right and right to left, alternatively. + ZigZag traverse: + Returns a list of nodes value from left to right and right to left, alternatively. """ + if root is None: + return [] + + output: list[Sequence[Node | None]] = [] + flag = 0 height_tree = height(root) + for h in range(1, height_tree + 1): - if flag == 0: - print_left_to_right(root, h) + if not flag: + output.append(get_nodes_from_left_to_right(root, h)) flag = 1 else: - print_right_to_left(root, h) + output.append(get_nodes_from_right_to_left(root, h)) flag = 0 + return output + def main() -> None: # Main function for testing. """ @@ -125,18 +155,23 @@ def main() -> None: # Main function for testing. """ All Traversals of the binary are as follows: """ - print(f" In-order Traversal is {inorder(root)}") - print(f" Pre-order Traversal is {preorder(root)}") - print(f"Post-order Traversal is {postorder(root)}") - print(f"Height of Tree is {height(root)}") - print("Complete Level Order Traversal is : ") - level_order(root) - print("\nLevel-wise order Traversal is : ") - for h in range(1, height(root) + 1): - print_left_to_right(root, h) - print("\nZigZag order Traversal is : ") - zigzag(root) - print() + + print(f"In-order Traversal: {inorder(root)}") + print(f"Pre-order Traversal: {preorder(root)}") + print(f"Post-order Traversal: {postorder(root)}", "\n") + + print(f"Height of Tree: {height(root)}", "\n") + + print("Complete Level Order Traversal: ") + print(level_order(root), "\n") + + print("Level-wise order Traversal: ") + + for level in range(1, height(root) + 1): + print(f"Level {level}:", get_nodes_from_left_to_right(root, level=level)) + + print("\nZigZag order Traversal: ") + print(zigzag(root)) if __name__ == "__main__":