当前位置: 首页 > 知识库问答 >
问题:

如何遍历由节点组成的二叉树?(内部代码)

轩辕实
2023-03-14

我被赋予一个类,它创建一个充满nodes.each节点的二叉树,它被赋予一个父节点和一个指向其左或右子节点的指针。

二叉树节点类:

class BTNode():
''' a class that represents a binary tree node'''
def __init__(self, data, parent=None, left_child=None, right_child=None):
    '''(BTNode, obj, BTNode, BTNode, BTNode) -> NoneType
    Constructs a binary tree nodes with the given data'''

    self._parent = parent
    self._left = left_child
    self._data = data
    self._right = right_child

def set_parent(self, parent):
    '''(BTNode, BTNode) -> NoneType
    set the parent to the given node'''
    self._parent = parent
def set_left(self, left_child):
    '''(BTNode, BTNode) -> NoneType
    set the left child to the given node'''
    self._left = left_child

def set_right(self, right_child):
    '''(BTNode, BTNode) -> NoneType
    set the right child to the given node'''
    self._right = right_child
def set_data(self, data):
    '''(BTNode, obj) -> NoneType
    set the data at this node to the given data'''
    self._data = data    

def get_parent(self):
    '''(BTNode) -> BTNode
    return the pointer to the parent of this node'''
    return self._parent

def get_left(self):
    '''(BTNode) -> BTNode
    return the pointer to the left child'''
    return self._left

def get_right(self):
    '''(BTNode) -> BTNode
    return the pointer to the right child'''
    return self._right   
def get_data(self):
    '''(BTNode) -> obj
    return the data stored in this node'''
    return self._data

def has_left(self):
    '''(BTNode) -> bool
    returns true if this node has a left child'''
    return (self.get_left() is not None)
def has_right(self):
    '''(BTNode) -> bool
    returns true if this node has a right child'''
    return (self.get_right() is not None)  
def is_left(self):
    '''(BTNode) -> bool
    returns true if this node is a left child of its parent'''
    # you need to take care of exception here, if the given node has not parent
    return (self.get_parent().get_left() is self)
def is_right(self):
    '''(BTNode) -> bool
    returns true if the given node is a right child of its parent'''
    # you need to take care of exception here, if the given node has not parent
    return (self.get_parent().get_right() is self)
def is_root(self):
    '''(BTNode) -> bool
    returns true if the given node has not parent i.e. a root '''
    return (self.get_parent() is None)

如何创建树的代码示例:

''' create this BT using BTNode
             A
           /   \
         B      C   
        /\       \
       D  E      F
                /
               G
'''
node_G = BTNode("G")
node_F = BTNode("F", None,node_G)
node_G.set_parent(node_F)
node_C = BTNode("C", None, None, node_F)
node_F.set_parent(node_C)
node_D = BTNode("D")
node_E = BTNode("E")
node_B = BTNode("B",None, node_D, node_E)
node_D.set_parent(node_B)
node_E.set_parent(node_B)
node_A = BTNode("A",None, node_B, node_C)
node_B.set_parent(node_A)

我不知道如何穿过这棵树。有人建议我使用递归,但我不确定如何使用。例如,如果树的高度最多相差1级,我需要返回true,因此上面的树将返回True。我该怎么做?谢谢!

共有2个答案

荆亦
2023-03-14

您可以遍历树的左侧和右侧,以找到叶的最大路径长度:

class Tree:
  def __init__(self, **kwargs):
    self.__dict__ = {i:kwargs.get(i) for i in ['value', 'left', 'right']}
  def get_length(self, current=[]):
    yield current+[1]
    yield from getattr(self.left, 'get_length', lambda _:[])(current+[1])
    yield from getattr(self.right, 'get_length', lambda _:[])(current+[1])
  def right_length(self):
    return len(max(getattr(self.right, 'get_length', lambda :[[]])(), key=len))
  def left_length(self):
    return len(max(getattr(self.left, 'get_length', lambda :[[]])(), key=len))

t = Tree(value = 'A', left=Tree(value='B', left=Tree(value='D'), right=Tree(value='E')), right = Tree(value='C', left = Tree(value='F', left=Tree(value='G'))))
print(t.right_length() - t.left_length())

输出:

1
谭建章
2023-03-14

尝试递归思考。让我们从几个定义开始。

  • 如果一棵树的左树和右树具有相同的高度,并且它的每一棵子树都是平衡的,那么它就是平衡的。此外,我们将一个空树定义为平衡的。
  • 树的高度,h(t) = 1 最大值(h(t.left), h(t.right))。在英语中,一棵树的高度是其较高的子树的高度的1。此外,我们假设一棵空树的高度为 0。

因此,对于树中的每个节点,我们可以检查其两个子节点的高度,并进行比较。如果它们不相等,我们知道树是不平衡的,我们返回false。

让我们首先定义代码来检查树是否平衡。

def is_balanced(node):
    if node is None:
        return True
    left_height = get_height(node.get_left())
    right_height = get_height(node.get_right())
    return left_height == right_height and is_balanced(node.get_left()) and is_balanced(node.get_right())

现在让我们定义我们上面使用的函数get_height。因为树的高度是它的子树高度的函数,所以我们可以使用递归。因为递归需要一个基本情况,所以我们不会无限递归,我们可以使用空树高度为0的事实。

def get_height(node):
    if node is None:
        return 0 # Assuming empty tree has a height of 0
    return 1 + max(get_height(node.get_left()), get_height(node.get_right()))

现在我们可以递归地遍历树,并通过在根上调用<code>is_balanced</code>来检查每个节点是否平衡。

is_balancednode_A

奖励练习:我给你的代码可以工作,但它不会很好地扩展。如果树变得非常大,它的运行速度会慢得多。为什么它很慢,你能做些什么来让它更快?

 类似资料:
  • 这是一个相当简单的问题,我注意到当我表示一棵树时,无论我用哪种方式(后排序,按顺序,前排序)树叶总是以相同的顺序出现,从左到右。 我只是想知道为什么,这是有原因的吗? 我刚开始研究它们,就想到了这个。 编辑: 我有一棵这样的树: 叶节点为:D、E和F 预购顺序为:A、B、D、C、E、F 顺序是:D,B,A,E,C,F 后序是:D,B,E,F,C,A 叶子节点总是从左到右出现,不管我选择哪个顺序,问

  • 假设我有一个简单的二叉树节点类,如下所示: 如何添加一个能够递归遍历任何大小的树的方法,从左到右访问每个现有节点,而无需重新访问已遍历的节点? 这行得通吗?

  • 本文向大家介绍javascript实现二叉树遍历的代码,包括了javascript实现二叉树遍历的代码的使用技巧和注意事项,需要的朋友参考一下 前言: 紧接着上篇 二叉树的javascript实现 ,来说一下二叉树的遍历。 本次一本正经的胡说八道,以以下这个二叉树为例子进行遍历: 接着是要引入二叉树实现的代码: 二叉树遍历的分类 二叉树的遍历分为先序、中序、后序遍历。这里说到的先序、中序、后序是相

  • 主要内容:层次遍历的实现过程,实现代码前边介绍了 二叉树的先序、中序和后序的遍历算法,运用了 栈的 数据结构,主要思想就是按照先左子树后右子树的顺序依次遍历树中各个结点。 本节介绍另外一种遍历方式:按照二叉树中的层次从左到右依次遍历每层中的结点。具体的实现思路是:通过使用 队列的数据结构,从树的根结点开始,依次将其左孩子和右孩子入队。而后每次队列中一个结点出队,都将其左孩子和右孩子入队,直到树中所有结点都出队,出队结点的先后顺序就是层

  • 为了上课,我必须创建一个状态对象的二叉树,每个状态对象包括一个居民对象的二叉树,这些居民对象组织住在每个州的人。我试图在一个给定的州中搜索最老的居民;然而,居民是按字母顺序组织在树中的,这对我的搜索毫无帮助。因此,我必须遍历整个居民树,更新保存最老的人的节点,并在树被完全遍历后返回它。我已经有了代码的第一部分,但是还停留在如何写递归的剩余部分。 状态树的方法: 然后是公共“包装器”状态树方法:

  • 中序遍历二叉树 按完全二叉树的层次遍历给出一棵二叉树的遍历序列(其中用0表示虚结点),要求输出该二叉树的深度及中序遍历该二叉树得到的序列。 输入格式: 首先输入一个整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据首先输入一个正整数n(n≤1000),代表给出的二叉树的结点总数(当然,其中可能包含虚结点)。结点编号均为正整数,且各不相同。 然后输入n个正整数,表示按完全二叉树(即第1层1