簡體   English   中英

迭代計算所有節點的子樹大小?

[英]Iteratively compute subtree sizes for all nodes?

我正在嘗試創建一個迭代版本:

def computeSize(id):
   subtreeSize[id] = 1
   for child in children[id]:
      computeSize(child)
      subtreeSize[id]+=subtreeSize[child]

“迭代”表示沒有遞歸,因為在Python中,如果您的圖很大並且在任何地方都有較長的線性鏈,則會產生堆棧遞歸錯誤。

嘗試為此使用堆棧(通過DFS算法對其建模),但是我在細節方面遇到困難:

def computeSubtreeSizes(self): #self.sizes[nodeID] has size of subtree
    stack = [self.rootID] #e.g. rootID = 1
    visited = set()

    while stack:
        nodeID = stack.pop()
        if nodeID not in visited:
            visited.add(nodeID)
            for nextNodeID in self.nodes[nodeID]:
                stack.append(nextNodeID)

例如,一旦我開始,我顯然將根ID從堆棧中彈出,但是在那之后,我基本上在子循環之后“丟失”了ID,並且以后無法分配其大小。

我是否需要第二個堆棧?

未經測試-考慮此偽代碼的概念是要處理一堆節點,並且在每個節點上有相應的堆棧其直接子節點尚未處理。 這意味着主堆棧上的每個項目都是一個元組-元組中的第一個項目是節點,第二個項目是未處理的子節點列表。

def computeSubtreeSizes(self):
    stack = [(self.rootID, [])] #e.g. rootID = 1
    visited = self.sizes = {}

    while stack:
        nodeID, subnodes = stack[-1]
        size = visited.get(nodeID)
        if size is None:
            # Haven't seen it before.  Set total to 1,
            # and set up the list of subnodes.
            visited[nodeID] = size = 1
            subnodes[:] = self.nodes[nodeID]
        if subnodes:
            # Process all the subnodes one by one
            stack.append((subnodes.pop(), []))
        else:
            # When finished, update the parent
            stack.pop()
            if stack:
                visited[stack[-1][0]] += size

明顯的潛在性能增強將是:不必費心添加已被訪問到主堆棧的節點。 僅在重復的子樹非常普遍時才有用。 這是更多代碼(可讀性較差),但可能看起來像這樣:

def computeSubtreeSizes(self):
    stack = [(self.rootID, [])] #e.g. rootID = 1
    visited = self.sizes = {}

    while stack:
        nodeID, subnodes = stack[-1]
        size = visited.get(nodeID)
        if size is None:
            # Haven't seen it before.  Add totals of
            # all previously visited subnodes, and
            # add the others to the list of nodes to
            # be visited.
            size = 1
            for sn in self.nodes[nodeID]:
                sn_size = visited.get(sn)
                if sn_size is None:
                    subnodes.append(sn)
                else:
                    size += sn_size
            visited[nodeID] = size

        if subnodes:
            # Process all the subnodes one by one
            stack.append((subnodes.pop(), []))
        else:
            # When finished, update the parent
            stack.pop()
            if stack:
                visited[stack[-1][0]] += size

編輯(尤其是測試后問題作者的編輯)當然是受歡迎的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM