每个节点的最远节点

时间:2015-12-18 13:16:26

标签: algorithm data-structures binary-tree

有没有办法为二叉树中的每个节点找到最远的节点。我知道树的diemeter的问题,但是关于每个节点的询问。我想在O(nlogn)中为n节点树使用算法。

2 个答案:

答案 0 :(得分:3)

分两步:

  • 计算每个节点的最远子项及其距离。这可以通过遍历树(O(n))后序来完成。

  • 对于每个节点:检查此节点及其每个父节点的最远子节点(向根节点移动时添加一个额外距离)。挑选最大的。 O(n logn)。

修改:如果您存储了最远的子项及其左右子树的距离,您可以遍历树预订并将所有结果都以O(n)为单位。

示例(没有标记哪个节点是最远的..实现细节):

       3.2       root
      /   \
     1*2  0.1
     / \    \
   0.0 1.1  0.0
       / \
     0.0 0.0

从根开始 - 通过父项的最长距离为0.

  • 最长距离为max(0,2,3)= 3.
  • 递归到左侧:将最大(0,2)+1作为通过父级的最长距离。
  • 向右递归:将最大(0,3)+1作为通过父母的最长距离。

在任何时候都有三种可能性:最长的路线经过父路线,它在左子树或右子树。访问节点时,所有这些距离都很容易获得。

答案 1 :(得分:0)

对于那些对基于Karolys sollution的python实现感兴趣的人:

第1步:仅向下搜索

  • 对于每个节点为每个节点,计算最远的孙子。
  • 对于每个节点,请记住我们发现的两个最扩展的分支

python代码:

def getFarGrandChild(node, tree, grandChildren):
    winner = None # {'node' : node, 'distance' : 0}
    second = None
    for child in tree.childrenOf(node):
        grandChild = getFarGrandChild(child, tree, grandChildren)
        if winner == None or grandChild['distance'] > winner['distance']:
            second = winner
            winner = grandChild
        elif second == None or grandChild['distance'] > second['distance']:
            second = grandChild

    grandChildren[node] = (winner, second)
    if winner == None:
        return {'child' : node, 
                'grandChild' : node,
                'distance' : 1}
    else:
        return {'child' : node, 
                'grandChild' : winner['grandChild'], 
                'distance' : winner['distance'] + 1}

第2步:向所有方向搜索

A与其子女和孙子女有关,也与其父母和祖父母及其他后代有关。我们称之为 nieces

  • 对于根,选择最远的节点:最远的孩子。
  • 对于每个孩子,选择最远的孩子或最远的侄女。 最远距离的侄女是来自另一个分支的最远的孩子。
  • 继续战争,因为最远的侄女现在可以来自另一个孩子或更高的孩子。

python代码:

def getFarRelative(node, tree, grandChildren, farNodes, niece = None):    
    winner, second = grandChildren[node]

    if niece != None:
        if winner == None or niece['distance'] > winner['distance']:
            second = winner
            winner = niece
        elif second == None or niece['distance'] > second['distance']:
            second = niece
    farNodes[node] = winner

    for child in tree.childrenOf(node):
        if child != winner['child']:
            getFarRelative(child, tree, grandChildren, farNodes, 
                niece  = {'child' :node, 
                        'grandChild' : winner['grandChild'],
                        'distance' : winner['distance'] + 1})
        elif second != None:
            getFarRelative(child, tree, grandChildren, farNodes, 
                niece  = {'child' : node, 
                        'grandChild' : second['grandChild'],
                        'distance' : second['distance'] + 1}) 

我创建了我的树

通过from graph import *

使用以下代码
# A set of data structures to represent graphs
#

class Node(object):
    def __init__(self, name):
        self.name = str(name)
    def getName(self):
        return self.name
    def __str__(self):
        return self.name
    def __repr__(self):
        return self.name
    def __eq__(self, other):
        return self.name == other.name
    def __ne__(self, other):
        return not self.__eq__(other)
    def __hash__(self):
        # Override the default hash method
        # Think: Why would we want to do this?
        return self.name.__hash__()

class Edge(object):
    def __init__(self, src, dest):
        self.src = src
        self.dest = dest
    def getSource(self):
        return self.src
    def getDestination(self):
        return self.dest
    def __str__(self):
        return '{0}->{1}'.format(self.src, self.dest)

class Digraph(object):
    """
    A directed graph
    """
    def __init__(self):
        # A Python Set is basically a list that doesn't allow duplicates.
        # Entries into a set must be hashable (where have we seen this before?)
        # Because it is backed by a hashtable, lookups are O(1) as opposed to the O(n) of a list (nifty!)
        # See http://docs.python.org/2/library/stdtypes.html#set-types-set-frozenset
        self.nodes = set([])
        self.edges = {}
    def addNode(self, node):
        if node in self.nodes:
            # Even though self.nodes is a Set, we want to do this to make sure we
            # don't add a duplicate entry for the same node in the self.edges list.
            raise ValueError('Duplicate node')
        else:
            self.nodes.add(node)
            self.edges[node] = []
    def addEdge(self, edge):
        src = edge.getSource()
        dest = edge.getDestination()
        if not(src in self.nodes and dest in self.nodes):
            raise ValueError('Node not in graph')
        self.edges[src].append(dest)

    def childrenOf(self, node):
        return self.edges[node]

    def hasNode(self, node):
        return node in self.nodes
    def __str__(self):
        res = ''
        for k in self.edges:
            for d in self.edges[str(k)]:
            #for d in self.edges[k]:
                res = '{0}{1}->{2}\n'.format(res, k, d)
        return res[:-1]

并在此树上测试

if __name__ == '__main__':
    # Create a tree :
    #            root
    #           /  \
    #          l    r
    #        /  \
    #       ll   lr
    #     /       \
    #    lll       lrr
    #   /           
    #  llll          

    myTree = Digraph()
    myTree.addNode(Node(str('root')))        
    myTree.addNode(Node(str('l')))   # for left
    myTree.addEdge(Edge(Node(str('root')), Node(str('l'))))
    myTree.addNode(Node(str('ll')))  # for left, left
    myTree.addEdge(Edge(Node(str('l')), Node(str('ll'))))        
    myTree.addNode(Node(str('lll'))) 
    myTree.addEdge(Edge(Node(str('ll')), Node(str('lll'))))        
    myTree.addNode(Node(str('llll'))) 
    myTree.addEdge(Edge(Node(str('lll')), Node(str('llll'))))        
    myTree.addNode(Node(str('lr')))  # for left, right
    myTree.addEdge(Edge(Node(str('l')), Node(str('lr'))))        
    myTree.addNode(Node(str('lrr'))) 
    myTree.addEdge(Edge(Node(str('lr')), Node(str('lrr'))))        
    myTree.addNode(Node(str('r'))) 
    myTree.addEdge(Edge(Node(str('root')), Node(str('r')))) 

使用这些陈述

    grandChildren = {}
    getFarGrandChild(Node('root'), myTree, grandChildren)
    for key in grandChildren:
        print key, grandChildren[key]
    print '\n'

    farNodes = {}
    getFarRelative(Node('root'), myTree, grandChildren, farNodes)
    print '\n'
    for key in farNodes:
        print key, farNodes[key]