Есть ли пример создания алгоритма Union & find без объединения по рангу в Omega (q log n)?

Недавно я прочитал этот и был удивлен, что временная сложность алгоритма объединения и поиска только со сжатием пути составила O((m+n) log n), где m — количество запросов «найти», а n — количество запросов на «слияние».

Меня заинтересовала эта сложность (поскольку я обычно реализую этот алгоритм без ранга, и даже когда я применил объединение по рангу вверх ногами, производительность была неплохой!) и попытался найти пример, который может сделать это время сложности. Но из-за огромной силы сжатия пути это было действительно сложно...

Есть ли какие-нибудь примеры, которые могут достичь Omega((m+n) log n), или эта сложность просто теоретическая, а не практическая?


person Love Paper    schedule 19.07.2014    source источник
comment
Что вы имеете в виду, например, фрагмент кода? Вы же не говорите, что уже сами написали этот алгоритм?   -  person Bergi    schedule 21.07.2014
comment
@Bergi Я имел в виду «пример» последовательности операций «слияния» и «найти». Например, объединить (1, 2), объединить (1, 3), найти (3).   -  person Love Paper    schedule 21.07.2014
comment
@Bergi: Без объединения по рангу это две строки кода. С объединением по рангу это пять строк кода. Неудивительно, что он реализовал это сам, и это не то, о чем он просит. Он спрашивает, как заставить его работать плохо.   -  person tmyklebu    schedule 21.07.2014


Ответы (2)


Да, существует соответствующая нижняя граница, созданная Майклом Дж. Фишером в 1972 году (см. раздел 3). В его примере используется биномиальное дерево глубины log n, где биномиальное дерево глубины 0 — это один узел, а биномиальное дерево глубины k — это два биномиальных дерева глубины k — 1, корень одного из которых указывает на корень другого. . Повторно беря объединение корней биномиального дерева, чтобы указать на один элемент, и выполняя поиск в самом глубоком узле, мы выполняем дорогостоящую (логарифмические шаги) операцию, которая оставляет для использования другое встроенное биномиальное дерево.

Демонстрация Python: это печатает (k+1) * 2**k, где k — аргумент example, представляющий приблизительное количество операций для O(2**k) операций с O(2**k) клавишами.

p = {}

def find(a):
    global count
    b = a
    while (b in p):
        count += 1
        b = p[b]
    while (a in p):
        pa = p[a]
        p[a] = b
        a = pa
    return b

def union(a, b):
    p[find(a)] = find(b)

def deepest():
    maxd = (0, None)
    for (a, pa) in p.items():
        d = 1
        while (pa in p):
            d += 1
            pa = p[pa]
        maxd = max(maxd, (d, a))
    return maxd[1]

def example(k):
    global count, p
    count = 0
    p.clear()
    for a in range(((2 ** k) - 1), 0, (- 1)):
        union(a, (a & (a - 1)))
    r = 0
    for a in range((2 ** k), (2 ** (k + 1))):
        union(r, a)
        find(deepest())
        r = a
example(9)
print(count)
person David Eisenstat    schedule 21.07.2014

или эта сложность чисто теоретическая, а не практическая?

да. сложность алгоритма — это чисто теоретическая конструкция для описания насколько хорошо алгоритм масштабируется при различных размерах входных данных (в данном случае, количестве находок и объединений).

Это не дает никаких гарантий относительно количества шагов, необходимых для конкретного экземпляра ввода (скажем: 5 находит и 3 объединения) — кроме конечного числа шагов. На самом деле большая нотация O использует понятие произвольно большой мультипликативной константы, что не помогает для расчета точного времени выполнения, но этого достаточно, чтобы различать алгоритмы по классам сложности.

person Bergi    schedule 21.07.2014
comment
Обратите внимание, что большая буква О предназначена для описания НАИБОЛЕЕ ВОЗМОЖНОГО РЕЗУЛЬТАТА. Во многих случаях производительность будет превосходить наихудший результат из-за характера расположения данных — в основном, в среднем вам повезло больше, чем в среднем. - person PaulProgrammer; 21.07.2014
comment
@PaulProgrammer: Не совсем так, вы можете выбрать лучший, худший или средний случай сложности анализ. Обозначение Big O также используется для анализа среднего случая. - person Bergi; 21.07.2014