预购,PostOrder,Python字典的InOrder

时间:2018-03-13 03:42:50

标签: python-3.x dictionary tree traversal

任何人都可以提供有关如何进行python词典常见遍历的任何帮助或建议吗?

这是我的示例数据(遍历维基百科页面进行遍历)

TREEDATA = [['F', 'B', 'A'],
    ['F', 'B', 'D', 'C'],
    ['F', 'B', 'D', 'E'],
    ['F', 'G', 'I', 'H']]

我有一个简单的函数来从这个数据创建一个dict

def createTree(allTransactionsMatrix):
    root = {}
    for transaction in allTransactionsMatrix:
        tempDict = root
        for item in transaction:
            tempDict = tempDict.setdefault(item, {})
    return root

我成功地为这个词典创建了一个预订遍历。

def preOrderTraversal(pyTree):
    for key, value in pyTree.items():
        print(key)
        if isinstance(value, dict):
            preOrderTraversal(value)

所以当我跑...

import json
pyTree = createTree(TREEDATA)
print(json.dumps(pyTree, indent=5))

我收到一本很好的词典

{
     "F": {
          "B": {
               "A": {},
               "D": {
                    "C": {},
                    "E": {}
               }
          },
          "G": {
               "I": {
                    "H": {}
               }
          }
     }
}

我可以获得这棵树的前序遍历

preOrderTraversal(pyTree)

带输出

F
B
A
D
C
E
G
I
H

然而,顺序和后序证明是困难的。

我对postorder的开始是在我访问它之后删除了一个叶子节点。然而,由于修剪/删除的工作原理,这并没有通过整个树。

def postOrderTraversal(pyTree):
    for key, value in list(pyTree.items()):
        if pyTree[key] == {}:
            print(key)
            del pyTree[key]
        else:
            postOrderTraversal(pyTree[key])

注意,我使用list(pyTree.items())的原因是因为在python 3中你无法删除当前的迭代器。它会知道并抛出错误。所以转换成一个列表让我顺其自然。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

字典非常适​​合我发现的可视化,但对于遍历方法并不好。所以我实现了一个python树类,可以是二进制或n-ary(但不是二叉搜索树,值和类型无关紧要)。

以下是所有遍历方法的代码和示例输出等。

from queue import *
import json
import itertools
import math


class Node:
    def __init__(self, val):
        self.val = val
        self.children = []
        self.freq = 1

    def get(self):
        return self.val

    def set(self, val):
        self.val = val

    def getChild(self, val):
        for each in self.children:
            if each.val == val:
                return each

    def getChildren(self):
        childArray = []
        for each in self.children:
            childArray.append(each.val)
        return childArray

    def printStats(self):
        print("Value: " + str(self.val) + " | " +
              "Frequency: " + str(self.freq) + " | " +
              "Children: " + ','.join(self.getChildren()))


class PythonTree:
    def __init__(self):
        self.root = Node("*root*")
        self.totalTreeNodes = 1
        self.totalInsertions = 1
        self.treeDepth = 0
        self.visualDict = {self.root.get()}

    def setVisualDict(self, passedMatrix):
        root = {}
        for transaction in passedMatrix:
            tempDict = root
            for item in transaction:
                tempDict = tempDict.setdefault(item, {})
        self.visualDict = root

    def addByMatrix(self, passedMatrix):
        self.setVisualDict(passedMatrix)
        for subArray in passedMatrix:
            currentNode = self.root
            tempLength = len(subArray)
            if tempLength > self.treeDepth:
                self.treeDepth = tempLength
            for each in subArray:
                self.totalInsertions += 1
                if each in currentNode.getChildren():
                    currentNode = currentNode.getChild(each)
                    currentNode.freq += 1
                else:
                    self.totalTreeNodes += 1
                    tempNode = Node(each)
                    currentNode.children.append(tempNode)
                    currentNode = tempNode

    def preOrder(self, currentNode, retArray):
        retArray.append(currentNode.get())
        for each in currentNode.children:
            self.preOrder(each, retArray)
        return retArray

    def preOrderTraversal(self):
        return self.preOrder(self.root, [])

    def inOrder(self, currentNode, retArray):
        whole = len(currentNode.children)
        half = math.ceil(whole / 2)

        for each in itertools.islice(currentNode.children, 0, half):
            self.inOrder(each, retArray)
        retArray.append(currentNode.get())
        for each in currentNode.children[half:]:
            self.inOrder(each, retArray)

        return retArray

    def inOrderTraversal(self):
        return self.inOrder(self.root, [])

    def postOrder(self, currentNode, retArray):
        for each in currentNode.children:
            self.postOrder(each, retArray)
        retArray.append(currentNode.get())
        return retArray

    def postOrderTraversal(self):
        return self.postOrder(self.root, [])

    def levelOrderTraversal(self):
        currentNode = self.root
        q = Queue()
        q.put(currentNode)
        output = []
        while q.qsize() > 0:
            currentNode = q.get()
            output.append(currentNode.val)
            for each in currentNode.children:
                q.put(each)
        return output

    def getStatsTraversal(self):
        currentNode = self.root

        mostFrequent = []
        leastFrequent = []
        maxVal = currentNode.freq
        minVal = currentNode.freq

        q = Queue()
        q.put(currentNode)
        while q.qsize() > 0:
            currentNode = q.get()
            currentNode.printStats()
            # Max Checks
            if currentNode.freq > maxVal:
                mostFrequent = [currentNode.get()]
                maxVal = currentNode.freq
            if currentNode.freq == maxVal:
                if currentNode.get() not in mostFrequent:
                    mostFrequent.append(currentNode.get())
            # Min Checks
            if currentNode.freq < minVal:
                leastFrequent = [currentNode.get()]
                minVal = currentNode.freq
            if currentNode.freq == minVal:
                if currentNode.get() not in leastFrequent:
                    leastFrequent.append(currentNode.get())

            for each in currentNode.children:
                q.put(each)
        return mostFrequent, leastFrequent, maxVal, minVal

    def getTreeStats(self):
        print("***Including the *root* node***\n")
        mostFrequent, leastFrequent, maxVal, minVal = self.getStatsTraversal()
        print("\nTotal Nodes: " + str(self.totalTreeNodes))
        print("Total Insertions ( greater than or equal to total Nodes ): " + str(self.totalInsertions))
        print("Depth of Tree: " + str(self.treeDepth))
        print("Most Frequent Nodes: " + str(mostFrequent) + " appeared (" + str(maxVal) + ") time(s)")
        print("Least Frequent Nodes: " + str(leastFrequent) + " appeared (" + str(minVal) + ") time(s)")
        avg = float(self.totalInsertions / self.totalTreeNodes)
        print("Average Node Frequency " + str(avg) + " (totalNodes/ totalInsertions")
        print(json.dumps(self.visualDict, indent=5))

这是一个示例运行(来自wiki的相同节点,刚刚修改过)。

myTree = PythonTree()
myTree.addByMatrix([['F', 'B', 'A'],
                    ['F', 'B', 'D', 'C'],
                    ['F', 'B', 'D', 'E'],
                    ['F', 'G', 'I', 'J'],
                    ['F', 'G', 'I', 'H']])

print("\nPRE ORDER TRAVERSAL")
print(myTree.preOrderTraversal())

print("\nLEVEL ORDER TRAVERSAL")
print(myTree.levelOrderTraversal())

print("\nIN ORDER TRAVERSAL")
print(myTree.inOrderTraversal())

print("\nPOST ORDER TRAVERSAL")
print(myTree.postOrderTraversal())

print("\nTREE STATS")
myTree.getTreeStats()

以及相关的输出。

PRE ORDER TRAVERSAL
['*root*', 'F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'J', 'H']

LEVEL ORDER TRAVERSAL
['*root*', 'F', 'B', 'G', 'A', 'D', 'I', 'C', 'E', 'J', 'H']

IN ORDER TRAVERSAL
['A', 'B', 'C', 'D', 'E', 'F', 'J', 'I', 'H', 'G', '*root*']

POST ORDER TRAVERSAL
['A', 'C', 'E', 'D', 'B', 'J', 'H', 'I', 'G', 'F', '*root*']

TREE STATS
***Including the *root* node***

Value: *root* | Frequency: 1 | Children: F
Value: F | Frequency: 5 | Children: B,G
Value: B | Frequency: 3 | Children: A,D
Value: G | Frequency: 2 | Children: I
Value: A | Frequency: 1 | Children: 
Value: D | Frequency: 2 | Children: C,E
Value: I | Frequency: 2 | Children: J,H
Value: C | Frequency: 1 | Children: 
Value: E | Frequency: 1 | Children: 
Value: J | Frequency: 1 | Children: 
Value: H | Frequency: 1 | Children: 

Total Nodes: 11
Total Insertions ( greater than or equal to total Nodes ): 20
Depth of Tree: 4
Most Frequent Nodes: ['F'] appeared (5) time(s)
Least Frequent Nodes: ['*root*', 'A', 'C', 'E', 'J', 'H'] appeared (1) time(s)
Average Node Frequency 1.8181818181818181 (totalNodes/ totalInsertions
{
     "F": {
          "B": {
               "A": {},
               "D": {
                    "C": {},
                    "E": {}
               }
          },
          "G": {
               "I": {
                    "J": {},
                    "H": {}
               }
          }
     }
}

如果您有任何疑问,请发表评论。我知道顺序遍历并不总是正确出现,但没有明确的方法来执行N-ary树的有序遍历。但其他方法应该是一致的。