将值范围内的元素分类到集群中的算法?

时间:2011-03-20 02:15:57

标签: algorithm

基本上我想列出一些像......

这样的东西
a 345
b 762
c 983
d 425
e 45
...

并给定最大距离,为包含该范围内其他元素的每个元素创建聚类。例如,如果我将上面的最大距离指定为300,则群集将是......

a 345
d 425
e 45

b 762
c 983

c 983
b 762

d 425
a 345

e 45
a 345

明智的约束,我正在阅读文件中的条目,这与我正在做的工作很常见。因此,我通常将我的算法集中在工作上,因为它读取条目,而不是读取文件中的所有内容,将其存储在一些方便的结构中,然后对其进行操作。无论如何,存储文件中的条目然后根据这些值执行排序,然后只是通过排序列表并进行适当的输出是我试图避免的。

我做了一些外行头脑风暴,但在我花了很多时间做一个彻底的分析之前,我觉得我已经在某个地方看过这个或者有一个非常类似的算法。我不是要求某人提出算法,除非你感到如此倾向,只是想知道是否有任何解决这个问题的现有问题或者与之类似的问题。

感谢。

1 个答案:

答案 0 :(得分:0)

另一种可能的泛滥填充算法,使用一些修改后的二进制搜索来减少所需的比较量:

Pseudo-code:
def clustersWithinRange(values, distance): //Should run in O(n log n)
    sortedValues = values.sorted()
    valueCount = values.len()
    clusters = Array()

    cachedLower = 0
    cachedUpper = values.len
    cachedValue = null

    for i in range(0, valueCount):
        value = sortedValues.get(i)
        if (cachedValue == value): //duplicate value, no need to calculate twice
            clusters.add(clusters.get(i).copy()) //simply clone last cluster or nop if no duplicate clusters wanted
        else:
            lower = sortedValues.binaryBoundSearch(values, value, distance, cachedLower, i, LowerBoundMatchFlag)
            upper = sortedValues.binaryBoundSearch(values, value, distance, cachedUpper, valueCount, UpperBoundMatchFlag)
            clusters.add(sortedValues[lower:upper+1])//add sublist within (and including) lower...upper to clusters
            cachedLower = lower
            cachedUpper = upper
    return clusters

    def withinDistance(valueA, valueB, distance):
        return abs(valueA - valueB) <= distance

    def binaryBoundSearch(values, value, distance, low, high, searchFlag):
        // Possible values of searchFlag:
        // "LowerBoundMatchFlag" to get the leftmost found match.
        // "UpperBoundMatchFlag" to get the rightmost found match.
        if (high < low):
            return -1 // not found
        mid = low + ((high - low) / 2)
        matchPosition = -1
        aValue = values[mid]
        if (withinDistance(aValue, value, distance)):
            matchPosition = mid
            displacement = (searchFlag == LowerBoundMatchFlag) ? -1 : 1
            if (mid > low && mid < high && withinDistance(values.get(mid + displacement), value, distance)):
                newLow = (searchFlag == LowerBoundMatchFlag) ? low : mid + displacement
                newHigh = (searchFlag == LowerBoundMatchFlag) ? mid + displacement : high
                matchPosition = binaryBoundSearch(values, value, newLow, newHigh, searchFlag)
        else:
            flag = compare(aValue, value)
            if (flag < 0): // current position too far left
                matchPosition = binaryBoundSearch(values, value, mid + 1, high, searchFlag)
            else if (flag > 0): // current position too far right
                matchPosition = binaryBoundSearch(values, value, low, mid - 1, searchFlag)

        return matchPosition