Complexidade de união-encontrar com caminho-compressão, sem classificação
A Wikipedia diz que a união por classificação sem compactação de caminho fornece uma complexidade de tempo amortizada de , e que a união por classificação e compactação de caminho fornece uma complexidade de tempo amortizada de (onde é o inverso da função Ackerman). No entanto, ele não menciona o tempo de execução da compactação do caminho sem a classificação da união, que é o que eu geralmente me implemento.O ( α ( n ) ) αO(logn)O(log⁡n)O(α(n))O(α(n))αα
Qual é a complexidade do tempo amortizado da união encontrar com a otimização de compactação de caminho, mas sem a união por otimização de classificação?
Observe que é o inverso da função Ackerman, não . Aqui "inverso" significa o inverso como uma função, não o recíproco: ou seja, se , , não . 1 / A ( n , n ) ) f ( n ) = O ( n , n ) α ( n ) = f - 1 ( n )α(n)α(n)1/A(n,n))1/A(n,n))f(n)=A(n,n)f(n)=A(n,n)α(n)=f−1(n)α(n)=f−1(n)1/f(n)1/f(n)
Entendo que essa é uma pergunta relativamente antiga, mas veja minha resposta e um artigo relevante: epubs.siam.org/doi/abs/10.1137/S0097539703439088 . Eu poderia ter perdido um ou dois detalhes ao copiar além dos limites. Nesse caso, por favor, sugira uma edição :-)
Seidel e Sharir provaram em 2005 [1] que o uso de compactação de caminhos com links arbitrários aproximadamente em operações tem uma complexidade de aproximadamente .mmO((m+n)log(n))O((m+n)log⁡(n))
Veja [1], Seção 3 (Vinculação arbitrária): Seja o tempo de execução da busca de união com operações elementos. Eles provaram o seguinte:f(m,n)f(m,n)mmnn
Reivindicação 3.1. Para qualquer número inteiro , temos .k>1k>1f(m,n)≤(m+(k−1)n)⌈logk(n)⌉f(m,n)≤(m+(k−1)n)⌈logk⁡(n)⌉
De acordo com [1], definir fornece .k=⌈m/n⌉+1k=⌈m/n⌉+1
Um limite semelhante foi dado usando um método mais complexo de Tarjan e van Leeuwen em [2], Seção 3:
Lema 7 de [2]. Suponha . Em qualquer sequência de operações de conjunto implementadas usando qualquer forma de compactação e vinculação ingênua, o número total de nós nos caminhos de localização é no máximo Com a ligação pela metade e ingênua, o número total de nós nos caminhos de busca é no máximo .m≥nm≥n(4m+n)⌈log⌊1+m/n⌋n⌉(4m+n)⌈log⌊1+m/n⌋⁡n⌉(8m+2n)⌈log⌊1+m/n⌋(n)⌉(8m+2n)⌈log⌊1+m/n⌋⁡(n)⌉
Lema 9 de [2]. Suponha que . Em qualquer sequência de operações de conjunto implementadas usando compactação e vinculação ingênua, o número total de nós nos caminhos de localização é no máximo .m<nm<nn+2m⌈logn⌉+mn+2m⌈log⁡n⌉+m
[1]: R. Seidel e M. Sharir. Análise de cima para baixo da compactação de caminho. Siam J. Computing, 2005, vol. 34, No. 3, pp. 515-525.
[2]: R. Tarjan e J. van Leeuwen. Análise de pior caso de algoritmos de união de conjuntos. J. ACM, vol. 31, n. 2, abril de 1984, pp. 245-281.
Não sei qual é o tempo de execução amortizado, mas posso citar uma possível razão pela qual, em algumas situações, você pode querer usar ambos, em vez de apenas a compactação de caminho: o pior caso de tempo de execução por operação é se você usa apenas a compactação de caminho, que é muito maior do que se você usasse a união por classificação e compactação de caminho.Θ(n)Θ(n)
Considere uma sequência de operações da União maliciosamente escolhidas para produzir uma árvore de profundidade (é apenas um caminho seqüencial de nós, em que cada nó é filho do nó anterior). A execução de uma única operação Find no nó mais profundo leva o tempo . Portanto, o pior tempo de execução por operação é .n - 1 Θ ( n ) Θ ( n )nnn−1n−1Θ(n)Θ(n)Θ(n)Θ(n)
Por outro lado, com a otimização de união por classificação, o pior caso de operação por operação é : nenhuma operação isolada pode demorar mais que . Para muitas aplicações, isso não importa: apenas o tempo total de execução de todas as operações (ou seja, o tempo de execução amortizado) será importante, e não o pior caso para uma única operação. No entanto, em alguns casos, o pior caso por operação pode importar: por exemplo, reduzir o pior caso por operação paraO ( log n ) O ( log n )O(logn)O(log⁡n)O(logn)O(log⁡n)O(logn)O(log⁡n) pode ser útil em um aplicativo interativo no qual você deseja garantir que nenhuma operação única possa causar um longo atraso (por exemplo, você deseja garantir que nenhuma operação única possa causar o congelamento do aplicativo por um longo tempo) ou em tempo real aplicativo em que você deseja garantir que sempre atenda às garantias em tempo real.