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

二叉树的测试有效性

翁俊良
2023-03-14

我需要一些关于递归函数使用的家庭作业问题的帮助。

我们希望通过嵌套元组表示二叉树,其中每个叶子都有一个字符串作为标签。我们要求叶子用不同的非空字符串标记,并且所有非叶节点都只有两个子节点。例如(('A','B'),'C'),('D',('F','E'))是有效的二叉树。

我要写一个递归函数valid_binary_tree(树),检查,即返回true或False,如果给定的树是一个递归元组,表示如上所述的二叉树。

我把这个问题分成两个功能。一个,检查字符串元组是否有效。即,它是不同字符串的元组,例如(' a ',' b ',' c '),但不是(' a ',' a ',' c ')等。

def validate_string_tuple(t):
"""
Validates whether input is a tuple of distinct strings.
1st step; check if input is a tuple
    if not, return False
2nd step; go through tuple; finds all 'leaves' of the tuple
    If any element is not a string, return False
3rd step; check for uniqueness of 'leaves'
    If length(list_of_leaves) != len(set_of_leaves) return False
"""
if isinstance(t,tuple):
    
    leaves_l=[]
    for i in range(len(t)):
        
        if isinstance(t[i],str) and t[i]!="":
            #Element in the tuple is a string. Append to list of leaves.
            leaves_l.append(t[i])
        else:
            #An element in the tuple is not a string.
            return False
    return (len(leaves_l)==len(set(leaves_l)))

else: return False

这似乎足够有效。我用< code>('ab ',(' c ',' d ')(False),< code>('a ',' a ',' b ',' c') (False),< code>('a ',' b ',' c') (True)测试过。

后一部分,为了检查整个树,我想我弄得相当混乱。它适用于某些输入,例如,如果在(('a','b'),'c'),('e',('f','g'))上使用,它会返回true。然而,它也在(('a','b'),'c','d')上返回true,这是不应该的(据我从描述中看出的?)。不管怎样,它非常不优雅,我相信它可以得到很大的改进。

def valid_binary_tree(tree):
"""
Checks if a tree (tuple) is a valid binary tree. All non-leaf nodes have
exactly two children, and all leaves are labeled by distinct strings.

- If the initial input is not a tuple, immediately return false.
"""
if not isinstance(tree,tuple):
    return False

#Initially true "list", since, for whatever reason, simply returning False below did not work.
bools=[True]
#Empty list to be populated with leaves (for checking uniqueness later)
leaves_l=[]
def traverse(tree):
    nonlocal leaves_l
    nonlocal bools
    
    if isinstance(tree, str):
        leaves_l+=(tree) #if we've gotten to a simple string (non tuple), it must be a leaf (str)
    
    elif validate_string_tuple(tree): #we've found a legit tuple.
        if len(tree)==2:
            leaves_l+=tree            #The tuple is of length 2, i.e. binary. Append to leaves.
            print('found a valid string tuple;',tree)
        else:
            print('found a string tuple of length >2') #non-binary tuple.
#return False had no effect here, even when the print was called. Hence the bools.append...
            bools.append(False)
    
    else:
        for child in tree: #recursively goes through tree, as it could have arbitrarily many nested tuples.
            traverse(child)

traverse(tree)

#check leaves list vs. set
if len(leaves_l)!=len(set(leaves_l)):
    print('Non-unique labels! Not a valid binary tree')
    return False
#Checks if any non-legit tuples have shown up
if all(bools): 
    return True
else: 
    return False

我也认识到这不可能是最优雅的方式,即使它在某些情况下确实有效。

共有1个答案

锺星洲
2023-03-14

看起来你把它复杂化了——需要应用一组非常简单的检查来确定给定的树(或该树中的任何给定节点)是否有效。

  • 是我们以前见过的叶子吗?False
  • 是我们没见过的叶子吗?
  • 不是元组,还是长度不对的元组?False
  • 两个子节点都验证吗?(这是递归部分!)

使用非本地和多级间接寻址会使您的代码难以调试,但我可以很容易地想象出一些错误:

  • 您的非本地状态从一个调用“泄漏”到下一个调用。(这正是大多数程序员避免全局/non-local的原因;这种类型的bug绝对是可怕的,调试起来也不好玩。)
  • 一些重要的数据没有从某个帮助函数传递给需要它的调用方。(同样,由于使用非本地等,这很复杂——当函数契约很混乱时,很难确定谁没有维护它们。)

只需在初始调用上创建并显式地将其传递给所有递归调用,就可以避免很多麻烦(并大大简化代码):

>>> def validate_tree(tree, leaves=None):
...     leaves = leaves or {None}
...     if isinstance(tree, str):
...         if tree in leaves:
...             return False  # duplicate leaf
...         leaves.add(tree)
...         return True  # unique leaf
...     if not isinstance(tree, tuple) or len(tree) != 2:
...         return False
...     return all(validate_tree(n, leaves) for n in tree)
...
>>> print(validate_tree(('a','a','b','c')))
False
>>> print(validate_tree(((('a','b'),'c'),('e',('f','g')))))
True
>>> print(validate_tree((('a','b'),'c','d')))
False
 类似资料:
  • 我目前正在尝试遍历二叉树以检查某些值是否在其中。for 循环正在测试 1 到 50 之间的所有值,并将为每个匹配的值返回 true。 这是当前的树: 现在我必须实现成员函数,我有正确的想法下来,但它在检查根后停止,根 - 前面所述的for循环打印输出 但仅此而已。 有人会通过伪代码或脚本提供一些方向吗?你不必给我代码,因为我想自己弄清楚。谢谢。

  • 我已经实现了一个二进制搜索树。我在JUNIT测试中的大部分测试都在进行中,包括这两个。我已在EntreIsPerfect()时实现了LeaveSisCorrect,并在AscendingOrderInCrementSheight()中插入了Values。 这两个测试都通过了,但根据他们的描述,我不知道它是否写得正确。 //TODO:请帮助我了解我是否已在InsertValues sinAscend

  • 二叉树 二叉树采用二叉链表存储,要求根据给定的先序遍历序列和中序遍历序列建立二叉树,并输出后序遍历序列、结点总数、叶子数、度为1的结点数、度为2的结点数。 输入格式: 测试数据有多组,处理到文件尾。每组测试数据的第一行输入结点数n(1≤n≤10),第二、三行各输入n个整数,分别表示二叉树的先序遍历序列和中序遍历序列。 输出格式: 对于每组测试,在一行上分别输出该二叉树的后序遍历序列,结点总数,叶子

  • 我正在学习,在本教程中,可以使用并发和通道来完成这个练习:解决方案。 我试图通过解决这个问题。我能想到的解决方案是使用临时数据结构来存储顺序遍历这两棵树的结果,然后进行比较。 例如,我使用存储顺序遍历的结果,然后进行比较(注意,我们正在比较排序的二叉树): 测试用例: 我想知道有没有其他更好的方法通过解决这个问题?

  • 主要内容:什么是二叉排序树?,使用二叉排序树查找关键字,二叉排序树中插入关键字,二叉排序树中删除关键字,总结前几节介绍的都是有关静态 查找表的相关知识,从本节开始介绍另外一种查找表—— 动态查找表。 动态查找表中做查找操作时,若查找成功可以对其进行删除;如果查找失败,即表中无该关键字,可以将该关键字插入到表中。 动态查找表的表示方式有多种,本节介绍一种使用树结构表示动态查找表的实现方法—— 二叉排序树(又称为 “二叉查找树”)。 什么是二叉排序树? 二叉排序树要么是空 二叉树,要么具有如下特点:

  • 对于插入二叉查找树的时间效率, 我知道插入的最佳/平均情况是O(log n),其中最坏的情况是O(n)。 我想知道的是,除了实现AVL(平衡BST)之外,是否还有任何方法可以确保在插入时始终具有最佳/平均情况? 谢谢