Как напечатать деревья с Unicode-линиями, связывающими узлы - PullRequest
0 голосов
/ 02 марта 2019

Я пытаюсь печатать деревья так, чтобы они выглядели лучше.В настоящее время я добавляю вкладки перед узлами, чтобы показать, на каком уровне они находятся.то есть:

top
    middle
        bottom
    middle1

Что я хочу сделать, это заменить вкладки строками Юникода, чтобы показать, как они связаны.то есть:

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 для каждого дочернего элемента узла

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...