美文网首页
python寻找树指定节点位置路径

python寻找树指定节点位置路径

作者: 就是大饼 | 来源:发表于2022-05-16 20:36 被阅读0次

    要求:文件中存有多行数据,每行数据有两列,如下例左图所示。意为树形数据,第一列为父节点,第二列为子节点,如下例右图所示。请读取文件,并实现给定节点,返回其路径关系。如给定节点B,返回1,2,6,B。

    示意图
    解法一:
    用列表存储数据,用index查找数据。
    # 获取到父、子节点
    f = open('tree.txt', 'r')
    txt = f.readlines()
    L_parent = []
    L_child = []
    for line in txt:
        line = line.strip('\n').split('\t')
        L_parent.append(line[0])
        L_child.append(line[1])
    f.close()
    
    search_node = input("请输入想寻找的节点:")
    child_index = []
    res = []
    
    
    # 找到子节点的索引位置
    def search_child_node(item):
        try:
            temp_child_index = L_child.index(item)
        except ValueError:
            print("未找到此节点")
            return
        else:
            if temp_child_index not in [0, 1, 2]:
                child_index.append(temp_child_index)
                search_child_node(L_parent[temp_child_index])
            else:
                child_index.append(0)
    
    
    # 根据子节点的索引位置找父节点
    def search_parent_node():
        for i in child_index:
            res.append(L_parent[i])
        res.reverse()
        res.append(search_node)
        print(res)
    
    
    search_child_node(search_node)
    search_parent_node()
    

    缺点:如果列表很长节点很多就会比较慢,因为index的方法本质上是迭代整个list。用字典(dictionary)可以优化速度和代码结构。

    解法二:
    用dictionary储存数据,再遍历查找字典

    # 获取到父、子节点
    f = open('tree.txt', 'r')
    txt = f.readlines()
    L_parent = []
    L_child = []
    for line in txt:
        line = line.strip('\n').split('\t')
        L_parent.append(line[0])
        L_child.append(line[1])
    f.close()
    
    
    # 生成树
    def initree():
        tree_dict = {}
        for i in range(len(L_child)):
            temp_lis = []
            for j in range(len(L_parent)):
                if L_parent[j] == L_parent[i]:
                    temp_lis.append(L_child[j])
            tree_dict[L_parent[i]] = tree_dict.get(L_parent[i], temp_lis)
        return tree_dict
    
    # 搜寻目标节点
    def search(item):
        for i in tree_lis:
            if item in i[1]:
                res.append(i[0])
                if item == L_parent[0]:
                    res.append(L_parent[0])
                    return
                else:
                    search(i[0])
    
    
    tree_dic = initree()
    tree_lis = list(tree_dic.items())
    res = []
    while 1:
        target = input("请输入您想查找的结点:")
        if target in L_child or target in L_parent:
            search(target)
            break
        else:
            print("该结点不在树文件中。请重新输入")
    res.reverse()
    res.append(target)
    print(res)
    

    缺点:虽然用了dictionary,但是好像并不了解为啥要用dictionary,也并没有利用上这种数据结构的优势。

    解法三:

    # 获取到父、子节点
    f = open('tree.txt', 'r')
    txt = f.readlines()
    L_parent = []
    L_child = []
    for line in txt:
        line = line.strip('\n').split('\t')
        L_parent.append(line[0])
        L_child.append(line[1])
    f.close()
    
    
    # 生成树
    def initree():
        tree_dict = {}
        for i in range(len(L_child)):
            temp_lis = []
            for j in range(len(L_parent)):
                if L_parent[j] == L_parent[i]:
                    temp_lis.append(L_child[j])
            child_node = tuple(temp_lis)
            tree_dict[child_node] = tree_dict.get(child_node, L_parent[i])
        return tree_dict
    
    
    # 搜索指定节点
    def search(item):
        for i in tree_lis:
            if item in i[0]:
                res.append(i[1])  # B 6 2 1
                search(i[1])
                if item == L_parent[0]:
                    return
    
    
    tree_dic = initree()
    '''
    tree_dic = {("2", "3", "4"): "1", ("5", "6"): "2", ("7",): "3", ("8", "9"): "4",
                ("A", "B"): "6", ("C", "D"): "7", ("E", ): "9",
                ("F", "G"): "E", ("H",): "G"}
    '''
    
    tree_lis = list(tree_dic.items())
    res = []
    
    # 获取指定节点并判断存在
    while 1:
        target = input("请输入您想查找的节点:")
        if target in L_child or target in L_parent:
            res.append(target)
            search(target)
            break
        else:
            print("该节点不在树文件中。请重新输入。")
    res.reverse()
    print(res)
    

    这个解法和第二种没区别,使用dictionary的方式完全不对,而且因此在initree使用了循环嵌套循环的两个for,会让脚本更冗余更慢,反而还不如第一版。
    在这里我有一个理解误区,以为要把一个父节点的子节点全部归为一个键值对中,如“("2", "3", "4"): "1"”。其实并不需要,这不会影响遍历结果。

    最后解法:

    def ReadTreeFile(file):
        f = open(file, 'r')
        node = []
        for line in f.readlines():
            line = line.strip('\n').split('\t')
            node.append(line)
        tree_dict = {}
        for i in node:
            tree_dict[i[1]] = i[0]
        return tree_dict
    # 此时的tree_dict = {'2': '1', '3': '1', '4': '1', '5': '2', '6': '2', '7': '3'.......}
    
    def main():
        file = input("请输入树文件:")
        tree = ReadTreeFile(file)
        target = input("请输入您需要查找的节点:")
        res = []
        while tree.get(target):
            res.append(target)
            target = tree.get(target)
        res.append(target)
        res.reverse()
        print(res)
    
    
    main()
    

    相关文章

      网友评论

          本文标题:python寻找树指定节点位置路径

          本文链接:https://www.haomeiwen.com/subject/qiiwurtx.html