Как найти высоту дерева python

Calculating python tree height for large data sets

I’m trying to get an efficient algorithm to calculate the height of a tree in Python for large datasets. The code I have works for small datasets, but takes a long time for really large ones (100,000 items) so I’m trying to figure out ways to optimize it but am getting stuck. Sorry if it seems like a really newbie question, I’m pretty new to Python. The input is a list length and a list of values, with each list item pointing to its parent, with list item -1 indicating the root of the tree. So with an input of: 5 4 -1 4 1 1 The answer would be 3 — the tree is: (, ]>] > Here is the code that I have so far:

import sys, threading sys.setrecursionlimit(10**7) # max depth of recursion threading.stack_size(2**25) # new thread will get stack of such size class TreeHeight: def read(self): self.n = int(sys.stdin.readline()) self.parent = list(map(int, sys.stdin.readline().split())) def getChildren(self, node, nodes): parent = children = [i for i, x in enumerate(nodes) if x == parent['key']] for child in children: parent['children'].append(self.getChildren(child, nodes)) return parent def compute_height(self, tree): if len(tree['children']) == 0: return 0 else: max_values = [] for child in tree['children']: max_values.append(self.compute_height(child)) return 1 + max(max_values) def main(): tree = TreeHeight() tree.read() treeChild = tree.getChildren(-1, tree.parent) print(tree.compute_height(treeChild)) threading.Thread(target=main).start() 

There is no question. If you are asking why it’s slow. It’s becasue you are doing several overkills, if your asking for an optimal version. well whole program would probably have to be redesigned. If you’re new, good job! Though algorithmically bad, it’s nice coding. You should go to the CodeReview SE. They love dissecting working programs.

Assuming most of the time is spent in the ‘for’ loops, substituting, map or a list comprehension or a generator expression (depending on what you need) may be a good option. Have a look here in the loop section wiki.python.org/moin/PythonSpeed/PerformanceTips. I have also found this article very helpful when trying to optimize in Python python.org/doc/essays/list2str.

Источник

Поиск в ширину на Python

Двоичные деревья вечны. По крайней мере, так думают технические менеджеры, занимающиеся наймом разработчиков. И когда на техническом собеседовании вас просят решить задачу, касающуюся двоичных деревьев, первое, что интервьюер захочет знать, — в ширину или в глубину?

В чем разница?

Когда говорят о поиске в ширину (Breadth First Search, BFS) и глубину (Depth First Search, DFS), имеется в виду порядок обхода узлов двоичного дерева. При обходе в глубину вы сначала опускаетесь к низу дерева, а потом идете в сторону, а при обходе в ширину — наоборот, начинаете с корня и спускаетесь сначала к его узлам-потомкам, обходите их, потом спускаетесь к потомкам потомков, обходите их, и так далее.

Читайте также:  Садоводство болезни фруктовых деревьев

Если взять в качестве примера двоичное дерево на этом рисунке, при BFS-подходе порядок обхода узлов будет следующим: 1, 2, 3, 4, 5.

В случае с DFS возможны разные варианты последовательности посещения узлов. Все зависит от того, будет это прямой, обратный или центрированный обход. Например, прямой обход выдаст 1, 2, 4, 5, 3. Мы разбирали эти три типа обхода в статье «Обход двоичного дерева на Python».

Реализация поиска в ширину на Python

Давайте посмотрим, как сделать BFS на Python. Начнем с определения нашего класса TreeNode. В нем должны быть только значение и левый и правый указатели.

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

1. Стратегия

Вот как мы будем обходить узлы:

  1. Найдем высоту дерева от корня до самого дальнего листа.
  2. В цикле переберем все уровни (заканчивая верхушкой).
  3. Обойдем каждый уровень, выводя все узлы.

2. Поиск высоты дерева

Чтобы обойти каждый уровень, нам нужно сначала узнать, сколько всего уровней в дереве. Для этого мы напишем специальный метод.

Да, вы угадали: метод будет рекурсивным, как и большинство методов для обхода двоичных деревьев. Давайте подумаем, каким будет базовый случай. Самый простой вариант — когда у нас нулевой корень. В этом случае высота — 0. Вам может показаться, что простейший случай — узел без потомков, но тогда нам придется проверять, есть ли потомки, а это уже увеличивает сложность.

def height(node): if not node: return 0

Что дальше? Нам нужно обойти левую и правую половину дерева. Мы будем вызывать метод height() для этих половин и сохранять в две переменные: l_height и r_height .

def height(node): if not node: return 0 l_height = height(node.left) r_height = height(node.right)

Какую высоту мы вернем: левую или правую? Конечно, большую! Поэтому мы берем max() обоих значений и возвращаем его. Не забудьте добавить 1 для текущего узла.

def height(node): if not node: return 0 l_height = height(node.left) r_height = height(node.right) return max(l_height, r_height) + 1

3. Перебор уровней в цикле

Теперь, когда у нас есть высота, мы можем приступить к написанию метода для обхода дерева в ширину. Единственный аргумент, который этот метод будет принимать, — корневой узел.

Затем нам нужно получить нашу высоту.

def breadth_first(root): h = height(root)

Наконец, мы перебираем в цикле высоту дерева. На каждой итерации мы будем вызывать вспомогательную функцию — print_level() , которая принимает узел root и уровень.

def breadth_first(root): h = height(root) for i in range(h): print_level(root, i)

4. Обход дерева

Мы будем обходить каждый уровень отдельно, выводя все узлы на нем. Тут нам пригодится наша вспомогательная функция. Она принимает два аргумента: корень и текущий уровень.

def print_level(root, level):

В этом методе номер уровня определяется индексом i цикла for . Чтобы обойти все дерево, мы будем рекурсивно двигаться по уровням, уменьшая i , пока не достигнем уровня 0. Когда достигнем, это будет означать, что теперь можно выводить узлы на экран.

Наш базовый случай — когда корень — null . Этот метод только выводит дерево на экран и ничего не возвращает, поэтому в базовом случае будет просто return .

def print_level(root, level): if not root: return

Далее, если наш уровень — 0 (то есть интересующий нас уровень), нам нужно вывести значение этого узла.

def print_level(root, level): if not root: return if level == 0: print(root.value)

Наконец, если номер уровня больше нуля, это означает, что нам нужно продолжить обход дерева. Мы вызываем наш рекурсивный метод для левой и правой половин дерева. Не забудьте отнять единицу от level в обоих вызовах функции.

def print_level(root, level): if not root: return if level == 0: print(root.value) elif level > 0: print_level(root.left, level - 1) print_level(root.right, level - 1)

Вот и все! Нам пришлось создать три разных метода, но в конечном итоге мы можем обойти дерево в ширину.

Читайте также:  Чпу лазерная резка дерева своими руками

5. Тестирование

Для начала давайте создадим дерево, используя наш класс TreeNode .

Теперь нужно заполнить оставшуюся часть дерева. При помощи следующих строк кода мы приведем дерево к тому виду, что изображен на схеме.

tree.left = TreeNode(2) tree.right = TreeNode(3) tree.left.left = TreeNode(4) tree.left.right = TreeNode(5)

Наконец, запускаем наш метод.

Ожидаемый результат: 1, 2, 3, 4, 5 . Мы успешно обошли дерево!

Источник

Сбалансированное бинарное дерево в Python

В этой статье мы будем изучать сбалансированные бинарные деревья, и мы постараемся реализовать программу в Python, чтобы определить, сбалансирован ли двоичное дерево или нет. Чтобы прочитать эту статью, вы должны быть знакомы с концепцией бинарных деревьев.

Что такое сбалансированное бинарное дерево?

Сбалансированное бинарное дерево определяется как бинарное дерево, в котором на каждом узле его левое поддерево и правое судно имеет равную высоту или их высоту отличаться всего на 1.

Другими словами, если мы рассмотрим любой узел дерева в качестве корня дерева, то высоты его левого подмаревки и правого подмаревки никогда не должны отличаться более чем на 1.

Как проверить, является ли бинарное дерево сбалансировано или нет?

Согласно определению высота левого поддерева и правого поддерева не должна превышать одного на любом узле.

Поэтому, если мы рассмотрим дерево, которое будет сбалансировано на любом узле, нам придется найти высоту его левого подделка и правого подмаревки.

Тогда мы проверим разницу в высотах. Если разница выйдет больше 1 на любом узле, мы объявим, что дерево не сбалансировано. Ниже приведен алгоритм для этой процедуры:

Algorithm CheckBalancedBinaryTree: Input: Root Node of the binary tree. Output:True if binary tree is balanced and False otherwise. Start. 0.If tree is empty, return True. 1. Check the height of left sub-tree. 2.Check the height of right sub-tree. 3.If difference in height is greater than 1 return False. 4.Check if left sub-tree is balanced. 5.Check if right sub-tree is balanced. 6. If left sub-tree is balanced and right sub-tree is also balanced, return True. End

Мы выяснили алгоритм для проверки, если бинарное дерево сбалансировано, но мы не знаем, как рассчитать высоту дерева и подделки. Таким образом, мы сначала реализуем программу, чтобы найти высоту дерева, если узел корневого узла, а затем мы реализуем вышеуказанный алгоритм.

Как найти высоту сбалансированного бинарного дерева?

Чтобы найти высоту бинарного дерева, мы можем просто помнить следующие пункты.

  • Если корень пуст, то высота дерева будет 0.
  • Если root не пустой, то высота дерева будет равна максимальной высоте левого подделка корневого и правого подделка корня, добавленного 1.
Читайте также:  Безопасная температура нагрева дерева

Имея в виду вышеуказанные точки, алгоритм нахождения высоты дерева:

  • Высота алгоритма (дерево):
  • Вход: root дерева
  • Выход: высота дерева
  • Начинать.
  • 1. Если корень нет, возврат 0.
  • 2.Нажмите высоту левого подделки .//Height(root.leftChild)
  • 3.Вы высота правого поддерева .//Height(root.rightChild)
  • 4.Видите максимальное значение в 2 и 3 и добавьте 1 к нему.
  • Конец

Теперь мы реализуем вышеуказанный алгоритм и выполните его для следующего бинарного дерева.

AskPython31 2.

Программа найти высоту бинарного дерева

Ниже приведен код для поиска высоты бинарного дерева.

class BinaryTreeNode: def __init__(self, data): self.data = data self.leftChild = None self.rightChild=None def insert(root,newValue): #if binary search tree is empty, make a new node and declare it as root if root is None: root=BinaryTreeNode(newValue) return root #binary search tree is not empty, so we will insert it into the tree #if newValue is less than value of data in root, add it to left subtree and proceed recursively if newValuehright: return hleft+1 else: return hright+1 root= insert(None,15) insert(root,10) insert(root,25) insert(root,6) insert(root,14) insert(root,20) insert(root,60) print("Printing the height of the binary tree.") print(height(root)) 
Output: Printing the height of the binary tree. 3

Теперь мы знаем, как найти высоту бинарного дерева. Таким образом, мы теперь будем реализовать алгоритм, чтобы проверить, является ли двоичное дерево сбалансировано или не для указанного выше двоичного дерева.

Программа для проверки, если бинарное дерево сбалансировано или нет

Следующая программа была реализована для проверки, если бинарное дерево сбалансировано или нет.

class BinaryTreeNode: def __init__(self, data): self.data = data self.leftChild = None self.rightChild=None def insert(root,newValue): #if binary search tree is empty, make a new node and declare it as root if root is None: root=BinaryTreeNode(newValue) return root #binary search tree is not empty, so we will insert it into the tree #if newValue is less than value of data in root, add it to left subtree and proceed recursively if newValuehright: return hleft+1 else: return hright+1 def CheckBalancedBinaryTree(root): #if tree is empty,return True if root==None: return True #check height of left subtree lheight= height(root.leftChild) rheight = height(root.rightChild) #if difference in height is greater than 1, return False if(abs(lheight-rheight)>1): return False #check if left subtree is balanced lcheck=CheckBalancedBinaryTree(root.leftChild) #check if right subtree is balanced rcheck=CheckBalancedBinaryTree(root.rightChild) #if both subtree are balanced, return True if lcheck==True and rcheck==True: return True root= insert(None,15) insert(root,10) insert(root,25) insert(root,6) insert(root,14) insert(root,20) insert(root,60) print("Printing True if binary tree is balanced:") print(CheckBalancedBinaryTree(root)) 
Output: Printing True if binary tree is balanced: True

Поскольку бинарное дерево в нашем примере сбалансировано, программа напечатала правда. Вы можете проверить его для несбалансированных бинарных деревьев, изменяя программу для вставки новых значений.

Заключение

В этой статье мы изучали концепцию сбалансированного бинарного дерева. Мы также обсудили алгоритмы нахождения высоты бинарного дерева и проверки, если бинарное дерево сбалансировано или нет. Оставайтесь настроиться на более информативные статьи.

Читайте ещё по теме:

Источник

Оцените статью