Русские Блоги
Python нерекурсивно реализует последующее обход бинарных деревьев
leetcode 145. Binary Tree Postorder Traversal
- Используйте один стек стека, чтобы сохранить корневые узлы, а другой флаг стека сохраняет, пересекает ли правый подперок каждого узла;
- Если корневой узел существует, узел входит в стек, и результат правильного ребенка узла установлен на 0, что означает, что он не проходит;
- Точка корня к левому подзадажному;
- Если стек не является пустым, определите, существует ли правая поддерева верхнего элемента стека и проехал ли он. Выйти из стека;
- Повторите 2-4, пока стек или корень не будет не существует.
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def postorderTraversal(self, root): """ :type root: TreeNode :rtype: List[int] """ ret = [] stack = [] flag = [] while root or stack: while root: stack.append(root) flag.append(0) root = root.left if stack: top = stack[-1] if top.right and not flag[-1]: flag[-1] = 1 root = top.right else: flag.pop() ret.append(stack.pop().val) return ret
Первый язык, который чувствует, когда я учился в школе, — это C, и структура данных также основана на обучении C.
Как и корневые узлы в последующем, сначала пересечь левое под -три, а затем пересечь правый подэрей. В это время подумайте: сначала пересечь корневой узел, затем пересечь правый поддерев и, наконец, левый подтолк -tree. Он пересекает тип, и, наконец, вывод результатов обхода в порядке, и первое обход заказано написано и хорошо понято ранее.
- Используйте узлы стека;
- Когда узел существует или стек не является пустым, судите узел;
- Когда узел существует, значение узла сохраняется, узел входит в стек, а указатель застегивается на правое дерево узла;
- Когда стек не пуст, узел выходит из стека, а точка направлена на левый подэри;
- Повторите 2-4, пока результат не будет получен;
- Выходной результат обратного порядка, используя список Python -1.
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution(object): def postorderTraversal(self, root): """ :type root: TreeNode :rtype: List[int] """ ret = [] stack = [] while root or stack: while root: ret.append(root.val) stack.append(root) root = root.right if stack: top = stack.pop() root = top.left return ret[::-1]
Источник
Обход двоичного дерева на Python
Да, двоичные деревья — не самая любимая тема программистов. Это одна из тех старых концепций, о целесообразности изучения которых постоянно ведутся споры. В работе вам довольно редко придется реализовывать двоичные деревья и обходить их, так зачем же уделять им так много внимания на технических собеседованиях?
Сегодня мы не будем переворачивать двоичное дерево (ффухх!), но рассмотрим пару методов его обхода. К концу статьи вы поймете, что двоичные деревья не так страшны, как кажется.
Что такое двоичное дерево?
Недавно мы разбирали реализацию связных списков на Python. Каждый такой список состоит из некоторого количества узлов, указывающих на другие узлы. А если бы узел мог указывать не на один другой узел, а на большее их число? Вот это и есть деревья. В них каждый родительский узел может иметь несколько узлов-потомков. Если у каждого узла максимум два узла-потомка (левый и правый), такое дерево называется двоичным (бинарным).
В приведенном выше примере «корень» дерева, т. е. самый верхний узел, имеет значение 1. Его потомки — 2 и 3. Узлы 3, 4 и 5 называют «листьями»: у них нет узлов-потомков.
Строим двоичное дерево на Python
Как построить дерево на Python? Реализация будет похожей на наш класс Node в реализации связного списка. В этом случае мы назовем класс TreeNode .
Определим метод __init__() . Как всегда, он принимает self . Также мы передаем в него значение, которое будет храниться в узле.
class TreeNode: def __init__(self, value):
Установим значение узла, а затем определим левый и правый указатель (для начала поставим им значение None ).
class TreeNode: def __init__(self, value): self.value = value self.left = None self.right = None
И… все! Что, думали, что деревья куда сложнее? Если речь идет о двоичном дереве, единственное, что его отличает от связного списка, это то, что вместо next у нас тут есть left и right .
Давайте построим дерево, которое изображено на схеме в начале статьи. Верхний узел имеет значение 1. Далее мы устанавливаем левые и правые узлы, пока не получим желаемое дерево.
tree = TreeNode(1) tree.left = TreeNode(2) tree.right = TreeNode(3) tree.left.left = TreeNode(4) tree.left.right = TreeNode(5)
Обход двоичного дерева
Итак, вы построили дерево и теперь вам, вероятно, любопытно, как же его увидеть. Нет никакой команды, которая позволила бы вывести на экран дерево целиком, тем не менее мы можем обойти его, посетив каждый узел. Но в каком порядке выводить узлы?
Самые простые в реализации обходы дерева — прямой (Pre-Order), обратный (Post-Order) и центрированный (In-Order). Вы также можете услышать такие термины, как поиск в ширину и поиск в глубину, но их реализация сложнее, ее мы рассмотрим как-нибудь потом.
Итак, что из себя представляют три варианта обхода, указанные выше? Давайте еще раз посмотрим на наше дерево.
При прямом обходе мы посещаем родительские узлы до посещения узлов-потомков. В случае с нашим деревом мы будем обходить узлы в таком порядке: 1, 2, 4, 5, 3.
Обратный обход двоичного дерева — это когда вы сначала посещаете узлы-потомки, а затем — их родительские узлы. В нашем случае порядок посещения узлов при обратном обходе будет таким: 4, 5, 2, 3, 1.
При центрированном обходе мы посещаем все узлы слева направо. Центрированный обход нашего дерева — это посещение узлов 4, 2, 5, 1, 3.
Давайте напишем методы обхода для нашего двоичного дерева.
Pre-Order
Начнем с определения метода pre_order() . Наш метод принимает один аргумент — корневой узел (расположенный выше всех).
Дальше нам нужно проверить, существует ли этот узел. Вы можете возразить, что лучше бы проверить существование потомков этого узла перед их посещением. Но для этого нам пришлось бы написать два if-предложения, а так мы обойдемся одним.
def pre_order(node): if node: pass
Написать обход просто. Прямой обход — это посещение родительского узла, а затем каждого из его потомков. Мы «посетим» родительский узел, выведя его на экран, а затем «обойдем» детей, вызывая этот метод рекурсивно для каждого узла-потомка.
# Выводит родителя до всех его потомков def pre_order(node): if node: print(node.value) pre_order(node.left) pre_order(node.right)
Просто, правда? Можем протестировать этот код, совершив обход построенного ранее дерева.
Post-Order
Переходим к обратному обходу. Возможно, вы думаете, что для этого нужно написать еще один метод, но на самом деле нам нужно изменить всего одну строчку в предыдущем.
Вместо «посещения» родительского узла и последующего «обхода» детей, мы сначала «обойдем» детей, а затем «посетим» родительский узел. То есть, мы просто передвинем print на последнюю строку! Не забудьте поменять имя метода на post_order() во всех вызовах.
# Выводит потомков, а затем родителя def post_order(node): if node: post_order(node.left) post_order(node.right) print(node.value)
Каждый узел-потомок посещен до посещения его родителя.
In-Order
Наконец, напишем метод центрированного обхода. Как нам обойти левый узел, затем родительский, а затем правый? Опять же, нужно переместить предложение print!
# выводит левого потомка, затем родителя, затем правого потомка def in_order(node): if node: in_order(node.left) print(node.value) in_order(node.right)
Вот и все, мы рассмотрели три простейших способа совершить обход двоичного дерева.
Источник
Русские Блоги
Python реализует обход двоичного дерева (рекурсивный и нерекурсивный)
class Node(object): def __init__(self,value=None,left=None,right=None): self.value = value self.left = left self.right = right def pre_traverse(root): """ Прохождение перед последовательностью :param root: :return: """ if root == None: return print(root.value) pre_traverse(root.left) pre_traverse(root.right) def mid_traverse(root): """ Вторичная обход :param root: :return: """ if root==None: return mid_traverse(root.left) print(root.value) mid_traverse(root.right) def after_traverse(root): """ Обход последовательности :param root: :return: """ if root==None: return after_traverse(root.left) after_traverse(root.right) print(root.value) root=Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('F')))) Печать (прохождение предварительной последовательности: ') pre_traverse(root) print('\n') Печать («Siye Traversing:») mid_traverse(root) print('\n') Печать (прохождение последовательности: ') after_traverse(root) print('\n') preList = list('DBACEGF') midList = list('ABCDEFG') afterList = [] ## Рфуры перед бинарным деревом в средней и последовательном обходе def find_tree(preList, midList, afterList): if len(preList) == 0: return if len(preList) == 1: afterList.append(preList[0]) return root = preList[0] n = midList.index(root) find_tree(preList[1:n + 1], midList[:n], afterList) find_tree(preList[n + 1:], midList[n + 1:], afterList) afterList.append(root) find_tree(preList,midList,afterList) print(afterList)
Проверка предварительной последовательности: D B A C E G F Субпоследовательная обход: A B C D E F G Охожание задней последовательности: A C B F G E D ['A', 'C', 'B', 'F', 'G', 'E', 'D']
class Tree(): # Дерево def __init__(self): self.root = Node() def add(self, data): # Добавить узел на дерево node = Node(data) Если self.root.data == -1: # Если дерево пустое, корневой узел назначен self.root = node else: my_queue = [] treeNode = self.root my_queue.append(treeNode) Пока My_Queue: # иерархические пересечения для существующих узлов treeNode = my_queue.pop(0) if not treeNode.left: treeNode.left = node return elif not treeNode.right: treeNode.right = node return else: my_queue.append(treeNode.left) my_queue.append(treeNode.right) Def pre_order_stack (self, root): # Обход последовательности реализации стека (нерешительный) if not root: return myStack = [] node = root while myStack or node: Пока узел: # из корневого узла, всегда ищите его левый поддель print(node.data) myStack.append(node) node = node.left Node = MyStack.pop () # В то время как концы указывают на то, что текущий узел узла пуст, то есть предыдущий узел не имеет левого дерева. Node = Node.right # Начните смотреть на своего правильного ребенка Def in_order_stack (self, root): # Стек внедрение последовательного обхода (нерешительный) if not root: return myStack = [] node = root Пока MyStack или Node: # из корневого узла, ищите его левый поддерево while node: myStack.append(node) node = node.left node = myStack.pop() print(node.data) node = node.right Def Post_Order_Stack (Self): # Последовательность реализации стека проездной (нерешительный) #Stext Корневой узел, затем пересекайте правое дерево человека, и, наконец, левый поддерева, чтобы вы могли перевести в тип, пройденный по заказу, и, наконец, только результаты прохождения находятся в обратном выходе. ОК. ОК. ОК. if not root: return myStack1 = [] myStack2 = [] node = root while myStack1 or node: while node: myStack2.append(node) myStack1.append(node) node = node.right node = myStack1.pop() node = node.left while myStack2: print(myStack2.pop().data) datas = [2, 3, 4, 5, 6, 7, 8, 9] Дерево = дерево () # недавно построенный объект дерева for data in datas: Tree.add (данные) # Присоединяйтесь к узлу дерева один за другим
Источник