查找使用简单几何级数创建的树的祖先节点

时间:2015-05-28 18:25:14

标签: python algorithm

我正在寻找一种算法,该算法将为使用几何系列创建的任何树中的任何节点提供祖先线,其中a = 1r等于任何整数。例如,下图中的树r = 226的祖先行是[26, 13, 6, 3, 1]

enter image description here

我自己也有过这方面的答案,并且得出了一个答案,似乎能够为我尝试的r的价值提供正确的答案。但在我创建一个使用此算法提供文件系统资源的应用程序之前,我想确保我不会遗漏某些边缘案例。感觉就像那种问题必须有一个既定的解决方案,几乎肯定比我的更优雅。有谁知道什么?

# My python implementation.

import math

def findLevelOfFolder(folder):
    """ Find the 'level' on which a given folder sits.  """
    if folder == 1:
        return 1
    else:
        level = 2
        while True:
            lower, upper= boundsOfLevel(level)
            if folder >= lower and folder <= upper:
                return level
            level += 1


def sumOfProgression(r, upToAndIncludingTerm):
    """
    Sums a simple geometric series.

    If r = 2, and upToAndIncludingTerm = 6, we'refinding the value of...
    pow(2, 0) + pow(2, 1) + pow(2, 3) + ... + pow(2, 5)
    """
    rRepeated = [r] * upToAndIncludingTerm
    powers = range(0, upToAndIncludingTerm)

    return sum(map(pow, rRepeated, powers))


def boundsOfLevel(level):
    """
    A levels 'bounds' refers to the number of the first folder and the last folder
    on that level. For example, when r == 2, and the level == 3, the
    bounds is (4, 7). The smallest possible level is 1, which, for any
    value of r always returns (1, 1).
    """
    assert(level > 0, "Smallest possible level is 1.")
    if level == 1:
        return 1, 1
    else:
        lower = sumOfProgression(foldersPerFolder, level-1) + 1
        upper = lower + pow(foldersPerFolder, level-1) - 1
        return lower, upper


def ancestorsOfFolder(folder, ancestors):
    """ Find the shortest route from folder '1' for the specified folder value.

    On completion, ancestors will contain a list of numbers each of which
    represents a folder in the ancestral line of 'folder'. The first number in
    the list will always be 'folder' and the last number will always be 1."""
    # First get the level...
    level = findLevelOfFolder(folder)
    lowerBoundOfPreviousLevel, _ = boundsOfLevel(level-1)

    relativePosition = folder - sumOfProgression(foldersPerFolder, level-1)
    parent = (lowerBoundOfPreviousLevel - 1) + math.ceil(relativePosition/foldersPerFolder)
    ancestors.append(parent)
    if parent != 1:
        ancestorsOfFolder(parent, ancestors)

# 'r' value
foldersPerFolder = 2

# looking for ancestral line of...
folder = 23

print(ancestorsOfFolder(folder, [folder])) # -> [23, 11, 5, 2, 1]

2 个答案:

答案 0 :(得分:3)

如果您将根编号为0,则更容易看到模式。

对于r = 4:

              0
     1     2        3      4
   5..8  9..12  13..16   17..20

在这种情况下,每个节点k都将floor((k-1)/r)作为其父级。

如果你在1开始编号,就像在

中一样
              1
     2     3        4      5
   6..9  10..13  14..17   18..21
它变得有点乱。在除以4之前,您需要减去某些内容,然后再添加其他内容。这些事情对我来说并不是很清楚。我的建议:如果可能的话,使用基于0的树:)

答案 1 :(得分:1)

第三次的魅力(无论如何,第三次编辑)。

每个级别的父级都可以使用等式def ancestorsOfFolder(folder, r): ancestors = [] while folder > 0: ancestors.append(folder) folder = (folder - 2) // r + 1 return ancestors 找到:

folder = (folder - 1) // r
编辑:我同意,最好使用从零开始的树。可以使用等式def ancestorsOfFolder(folder, r): ancestors = [] while folder > 0: ancestors.append(folder) folder = (folder - 1) // r ancestors.append(0) return ancestors 找到父母。这是代码:

SELECT DISTINCT tmp.Arrival, tmp.Flight,
       COUNT(*) OVER (PARTITION BY Flight) as NumPassengers, 
       SUM(CASE WHEN SegmentNumber = 1 AND LegNumber = 1 THEN 1 ELSE 0 END) OVER
           (PARTITION BY Flight, Arrival)
          ) as NumLocalPassengers,
       STD, STA   
FROM #TempLocalOrg tmp;