Cách truy cập các nút trong cây nhị phân - lặp đi lặp lạiẢnh của Susan Q Yin trên unplashViệc viết mã đệ quy rất đơn giản là rất đơn giản. Ngăn xếp được sử dụng nội bộ cho đệ quy. Trong blog này, chúng tôi sử dụng Stack và Hàng đợi để thực hiện các đường truyền cây lặp đi lặp lại. Thứ tựSubtree trái → Root → Subtree bên phải
Approach: - Tạo một ngăn xếp trống và đẩy nút gốc.
- khai báo một biến để theo dõi nút hiện tại
- Chạy trong khi vòng lặp cho đến khi ngăn xếp không trống hoặc nút hiện tại không có
- Chúng tôi tiếp tục thêm nút hiện tại còn lại trong ngăn xếp.
- Khi nút hiện tại trở thành không có & ngăn xếp không trống, chúng tôi bật phần tử từ ngăn xếp và gán nó dưới dạng nút hiện tại.
- Xử lý nút hiện tại và sau đó đặt nút hiện tại thành nút hiện tại bên phải.
def inorder_traversal(root): res = [] if not root: return res stack = [] curr_node = root while curr_node or stack: while curr_node: stack.append(curr_node) curr_node = curr_node.left curr_node = stack.pop(); res.append(curr_node.val); curr_node = curr_node.right; return res Đặt hàng trướcRoot → Subtree bên trái → Subtree phải
Approach: - Tạo một ngăn xếp trống và đẩy nút gốc.
- khai báo một biến để theo dõi nút hiện tại
- Chạy trong khi vòng lặp cho đến khi ngăn xếp không trống hoặc nút hiện tại không có
- Chúng tôi tiếp tục thêm nút hiện tại còn lại trong ngăn xếp.
- Khi nút hiện tại trở thành không có & ngăn xếp không trống, chúng tôi bật phần tử từ ngăn xếp và gán nó dưới dạng nút hiện tại.
- Xử lý nút hiện tại và sau đó đặt nút hiện tại thành nút hiện tại bên phải.
def preorder_traversal(root): res = [] if not root: return res stack = [root] while stack: curr_node = stack.pop() res.append(curr_node.val) if curr_node.right: stack.append(curr_node.right) if curr_node.left: stack.append(curr_node.left) return res Đặt hàng trướcRoot → Subtree bên trái → Subtree phải
Approach: - Chạy trong khi vòng lặp cho đến khi ngăn xếp không trống
- Chúng tôi bật ngăn xếp và gán nút bật lên làm nút hiện tại
- Xử lý nút hiện tại
- Đẩy nút hiện tại bên phải và các nút bên trái từng cái một
- Bưu điện
- Subtree trái → Subtree bên phải → root
- Chúng tôi tạo hai ngăn xếp, một để theo dõi nút hiện tại và một ngăn nữa để theo dõi đúng trẻ em.
def postorder_traversal(root): res = [] if not root: return res curr_node = root stack = [] right_stack = [] while stack or curr_node: if curr_node: if curr_node.right: right_stack.append(curr_node.right) stack.append(curr_node) curr_node = curr_node.left else: curr_node = stack[-1] if right_stack and curr_node.right == right_stack[-1]: curr_node = right_stack.pop() else: res.append(curr_node.val) stack.pop() curr_node = None return res Chúng tôi chạy vòng lặp trong khi ngăn xếp nút hiện tại không trống hoặc nút hiện tại không phải là không có Chúng tôi đẩy nút hiện tại ngay trong ngăn xếp trẻ em bên phải def buildTree(inorder, postorder): in_order_idx, post_order_idx = len(inorder)-1, len(postorder)-1 switch_side = False prev = root = TreeNode(postorder[post_order_idx]) stack = [root] post_order_idx -= 1 while post_order_idx >=0 : if stack and inorder[in_order_idx] == stack[-1].val: prev = stack.pop() in_order_idx -= 1 switch_side = True else: node = TreeNode(postorder[post_order_idx]) if not switch_side: prev.right = node prev = prev.right else: prev.left = node prev = prev.left switch_side = False stack.append(node) post_order_idx -= 1 return root Nút hiện tại được đẩy lên ngăn xếpNút hiện tại được đặt thành con trái của nó
Approach: Nếu đúng đứa trẻ được xử lý, chúng tôi xử lý nút hiện tại def level_order(root): if not root: return [] from collections import deque q = deque([(root, 0)]) level_map = {} while q: node, level = q.popleft() if level not in level_map: level_map[level] = [node.val] else: level_map[level].append(node.val) if node.left: q.append((node.left, level+1)) if node.right: q.append((node.right, level+1)) n = max(level_map) return [level_map[level] for level in range(n+1)] Nếu nút bên phải không được xử lý, chúng tôi xử lý nút hiện tại và đặt nút hiện tại là không có. Biểu đồ dưới đây tóm tắt biểu diễn mảng của ba lần trên. Những quan sát này giúp chúng ta tái tạo cây nhị phân cho các đường truyền. Sử dụng thuộc tính trên, chúng ta có thể xây dựng một cây nếu chúng ta đã được cung cấp thông tin và bưu điện. def right_view(root): if not root: return [] level_map = {} from collections import deque q = deque([(root, 0)]) while q: node, level = q.popleft() if level not in level_map: level_map[level] = node.val if node.left: q.append((node.left, level+1)) if node.right: q.append((node.right, level+1)) n = max(level_map) return [level_map[level] for level in range(n+1)] Lệnh cấp Root → Tất cả trẻ em → Tất cả trẻ em của cấp độ cuối cùng def right_view(root): if not root: return [] level_map = {} from collections import deque q = deque([(root, 0)]) while q: node, level = q.popleft() level_map[level] = node.val if node.left: q.append((node.left, level+1)) if node.right: q.append((node.right, level+1)) n = max(level_map) return [level_map[level] for level in range(n+1)] Chúng tôi sử dụng cấu trúc dữ liệu bản đồ để lưu trữ tất cả các nút ở cùng cấp độ. Chúng tôi cũng sử dụng một hàng đợi để xử lý các nút. Chúng tôi bật từ phía bên trái của quá trình hàng đợi các nút và sau đó thêm nút hiện tại trẻ em vào cuối hàng đợi. Trong khi chúng tôi làm như vậy, chúng tôi tăng mức độ của nút. Các vấn đề đã được giải quyết bằng cách sử dụng Traversal theo thứ tự cấp độ: Chế độ xem bên trái Ý tưởng: Chỉ số đầu tiên của danh sách các nút theo thứ tự cấp độ ở mọi cấp độ. from collections import deque def top_view(root): if not root: return [] pos_map = {} q = deque([(root, 0)]) while q: node, pos = q.popleft() if pos not in pos_map: pos_map[pos] = node.val if node.left: q.append((node.left, pos-1)) if node.right: q.append((node.right, pos+1)) m, n = min(pos_map), max(pos_map) return [pos_map[pos] for pos in range(m, n+1)] Chế độ xem bên phải Ý tưởng: Chỉ số cuối cùng của danh sách các nút theo thứ tự cấp độ ở mọi cấp độ. from collections import deque def top_view(root): if not root: return [] pos_map = {} q = deque([(root, 0)]) while q: node, pos = q.popleft() pos_map[pos] = node.val if node.left: q.append((node.left, pos-1)) if node.right: q.append((node.right, pos+1)) m, n = min(pos_map), max(pos_map) return [pos_map[pos] for pos in range(m, n+1)] Thứ tự hàng đầu Trong lần đi ngang này, chúng tôi duy trì khoảng cách từ gốc (trái → -1 & phải → +1). Chúng tôi lưu trữ danh sách các nút ở cùng một khoảng cách trong khóa đối tượng bản đồ là khoảng cách.PlainEnglish.io. Sign up for our free weekly newsletter. Follow us on
Twitter andLinkedIn. Join our community Discord. |