如何使用链接节点的Unicode行打印树

2024-06-25 23:08:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我试着用一种更好看的方式打印树木。目前,我在节点之前添加选项卡,以显示它们处于什么级别。i、 电子邮件:

top
    middle
        bottom
    middle1

我要做的是用unicode行替换选项卡,以显示它们是如何链接的。i、 电子邮件:

top
├── middle
│   └── bottom
└── middle1

这就是CHAIDS树所做的,这也是我想要实现的

我当前的代码:

import pickle


class Node:
    def __init__(self, data=None):
        self.data = data
        self.nextNodes = []
        self.level = 0

    def printNodes(self, startPoint=None):
        if startPoint:
            if self.data == startPoint:
                print(('\t' * self.level) + self.data)
                if self.nextNodes:
                    for i in self.nextNodes:
                        i.level = self.level + 1
                        i.printNodes()
                self.level = 0
            else:
                if self.nextNodes:
                    for i in self.nextNodes:
                        i.printNodes(startPoint)
        else:
            print(('\t' * self.level) + self.data)
            if self.nextNodes:
                for i in self.nextNodes:
                    i.level = self.level + 1
                    i.printNodes()
            self.level = 0

    def findVal(self, value):
        if self.data != value:
            if self.nextNodes:
                for i in self.nextNodes:
                    if i.findVal(value):
                        return True
        else:
            return True

    def deleteRequest(self, data, startPoint=None):
        if startPoint:
            if self.data == startPoint:
                if self.nextNodes:
                    for counter, i in enumerate(self.nextNodes):
                        if i.data == data:
                            self.nextNodes.pop(counter)
                            return True
                    for i in self.nextNodes:
                        return i.deleteRequest(data)
            else:
                if self.nextNodes:
                    for i in self.nextNodes:
                        return i.deleteRequest(data, startPoint)
        else:
            if self.nextNodes:
                for counter, i in enumerate(self.nextNodes):
                    if i.data == data:
                        self.nextNodes.pop(counter)
                        return True
                for i in self.nextNodes:
                    return i.deleteRequest(data)

    def modifyRequest(self, data, newData, startPoint=None, childModification=None):
        if startPoint:
            if startPoint == self.data or childModification:
                if self.data == data:
                    self.data = newData
                else:
                    if self.nextNodes:
                        for i in self.nextNodes:
                            return i.modifyRequest(data, newData, startPoint, childModification)
        else:
            if self.data == data:
                self.data = newData
                return True
            else:
                if self.nextNodes:
                    for i in self.nextNodes:
                        return i.modifyRequest(data, newData)

    def insertRequest(self, data, parent):
        if self.data == parent:
            for i in self.nextNodes:
                if i.data == data:
                    return False
            temp = Node(data)
            self.nextNodes.append(temp)
            return True
        else:
            if self.nextNodes:
                for i in self.nextNodes:
                    return i.insertRequest(data, parent)


class Head:
    def __init__(self):
        self.headNode = None

    def printList(self, startPoint=None):
        print('--TREE--')
        self.headNode.printNodes(startPoint)
        print('\n')

    def findVal(self, value):
        if self.headNode.findVal(value):
            print("'%s' found" % value)
        else:
            print("'%s' not found" % value)

    def insertNode(self, data, parent):
        if self.headNode.insertRequest(data, parent):
            print("Successfully added a node %s" % data)
        else:
            print("Unsuccessfully added a node")

    def deleteNode(self, data, startingPoint=None):
        if self.headNode.deleteRequest(data, startingPoint):
            print("Node %s has been successfully deleted" % data)
        else:
            print("Node %s has not been deleted - it was not found or it was the head node" % data)

    def modifyNode(self, data, newData, startingPoint=None):
        if self.headNode.modifyRequest(data, newData, startingPoint):
            print("Node %s has successfully changed to %s" % (data, newData))
        else:
            print("Node modification unsuccessful")

help = ''''
---TREE---
use treeN to use tree

-p x       prints the tree, 'x' being the optional starting point

-fv x      finds value 'x' in tree

-i x y     inserts a node, with 'x' being the data and 'y' being the parent
           can't have multiple siblings with the same name

-d x y     deletes a node with 'x' being the data type and optional 'y' being the parent(excluding)

-m x y z   modifies a node, with 'x' being the old data, 'y' being the new data
           and 'z' being the optional parent(excluding)

-s x       save to a file, 'x' being the file name, exclude extension

-l x       load a tree from a file, 'x' being the file name, exclude extension

-exit      exits the program

Rules:
    + one command per input
    + use ; as separators, leave no spaces
'''

print(help)

inp = input("Name of head Node: ")
tree = Head()
NH = Node(inp)
tree.headNode = NH

while True:
    try:
        inp = input('Enter command, type ? for help')
        if inp == '?':
            print(help)

        command = inp.split(';')
        commandL = len(command)
        cmdPrompt = command[0]
        if cmdPrompt == '-exit':
            break

        elif cmdPrompt == '-p':
            if commandL != 1 and commandL != 2:
                print("Incorrect amount of arguments")
                continue
            else:
                if commandL == 2:
                    tree.printList(command[1])
                else:
                    tree.printList()

        elif cmdPrompt == '-fv':
            if commandL != 2:
                print("Incorrect amount of arguments")
                continue
            else:
                tree.findVal(command[1])

        elif cmdPrompt == '-i':
            if commandL != 3:
                print("Incorrect amount of arguments")
                continue
            else:
                tree.insertNode(command[1], command[2])

        elif cmdPrompt == '-d':
            if commandL != 2 and commandL != 3:
                print("Incorrect amount of arguments")
                print(command)
                continue
            else:
                if commandL == 2:
                    tree.deleteNode(command[1])
                elif commandL == 3:
                    tree.deleteNode(command[1], command[2])

        elif cmdPrompt == '-m':
            if commandL != 3 and commandL != 4:
                print("Incorrect amount of arguments")
                continue
            elif commandL == 3:
                tree.modifyNode(command[1], command[2])
            elif commandL == 4:
                tree.modifyNode(command[1], command[2], command[3])

        elif cmdPrompt == '-s':
            if commandL != 2:
                print("Incorrect amount of arguments")
                continue
            else:
                fName = command[1] + '.p'
                pickle.dump(tree, open(fName, 'wb'))
                print("Successfully saved to file '%s'" % fName)

        elif cmdPrompt == '-l':
            if commandL != 2:
                print("Incorrect amount of arguments")
                continue
            else:
                fName = command[1] + '.p'
                tree = pickle.load(open(fName, 'rb'))
                print("Successfully loaded tree '%s'" % fName)
    except BaseException as error:
        print("Something went wrong: %s" % error)


print('done')

现在,我正在用我认为的预先排序的方式遍历这棵树-

  1. 打印当前节点
  2. 检查是否有任何子节点
  3. 如果确实存在子节点,请对节点的每个子节点运行步骤1和2

此树不是二进制的,这意味着每个节点可以有任意数量的子节点,而不受左或右的限制

考虑到每个节点有多少子节点,我已经尝试向每个子节点发送级别和所需的符号,但由于树变得更复杂,所以没有成功


Tags: theinselftreefordatareturnif