Sürgülü pencere medyanını hesaplamak için önemsiz algoritma


25

Çalışan medyanı hesaplamam gerekiyor:

  • Giriş: , k , vektör ( x 1 , x 2 , , x n ) .nk(x1,x2,,xn)

  • Çıkış: vektörü , y i ortancasıdır ( x i , x i + 1 , ... , x i + k - 1 ) .(y1,y2,,ynk+1)yi(xi,xi+1,,xi+k1)

(Yaklaşımlarla aldatma yok; Kesin çözümlere sahip olmak istiyorum. Elements büyük tamsayılar.)xi

boyutunda bir arama ağacını koruyan önemsiz bir algoritma vardır ; toplam çalışma süresi O ( n log k ) ' dır . (Burada bir "arama ağacı", logaritmik zamandaki ekleme, silme ve ortanca sorguları destekleyen bazı verimli veri yapılarını ifade eder.)kO(nlogk)

Ancak, bu bana biraz aptal görünüyor. Sadece medyanayı değil, k boyutundaki tüm pencerelerde tüm sipariş istatistiklerini etkili bir şekilde öğreneceğiz . Ayrıca, bu pratikte çok çekici değildir, özellikle kkk büyükse (büyük arama ağaçları yavaş olma eğilimindedir, bellek tüketiminde ek yük önemsiz değildir, önbellek verimliliği genellikle düşüktür, vb.).

Daha iyi bir şey yapabilir miyiz?

Daha düşük sınırlar var mı (örneğin karşılaştırma modeli için önemsiz algoritma asimptotik olarak optimal mi?)?


Düzenleme: David Eppstein karşılaştırma modeli için güzel bir alt sınır verdi! Yine de önemsiz algoritmadan biraz daha akıllıca bir şey yapmanın mümkün olup olmadığını merak ediyorum?

Örneğin, bu satırlar boyunca bir şeyler yapabilir miyiz: giriş vektörünü boyutunda parçalara böler ; her bir parçayı sıralayın (her bir elemanın orijinal konumlarını takip ederek); ve daha sonra, yardımcı veri yapıları olmadan verimli çalışan ortancaları bulmak için parçalara ayrılmış vektörleri kullanın. Tabii ki bu hala O ( n log k ) olacaktır , ancak pratikte dizilerin sıralanması arama ağaçlarının korunmasından çok daha hızlı olma eğilimindedir.kO(nlogk)


Düzenleme 2: Saeed, sıralama işleminin arama ağacı işlemlerinden daha hızlı olduğunu düşündüğüm nedenleri görmek istedi. İşte , n = 10 8 için çok hızlı karşılaştırmalar :k=107n=108

  • ≈ 8s: sıralama vektörleri ile k elemanları, hern/kk
  • ≈ 10s: elemanlı bir vektörü sıralaman
  • ≈ 80'ler: boyutu bir karma tablo ekleme & silme knk
  • ≈ 390s: , k boyutunda dengeli bir arama ağacına yapılan yerleştirmeler ve silmelernk

Karma tablo sadece karşılaştırma için var; Bu uygulamada doğrudan kullanım yok.

Özetle, sıralama ve dengeli arama ağacı işlemlerinin performansında neredeyse 50 faktör farkımız var. Ve arttıkça işler daha da kötüleşiyor .k

(Teknik detaylar: Veriler = rastgele 32 bit tam sayılar. Bilgisayar = tipik bir modern dizüstü bilgisayar. Test kodu standart kütüphane yordamları (std :: sort) ve veri yapıları (std :: multiset, std ::) kullanılarak C ++ dilinde yazılmıştır. sıralanmamış_multiset) İki farklı C ++ derleyicisi (GCC ve Clang) ve standart kitaplığın iki farklı uygulamasını kullandım (libstdc ++ ve libc ++).


1
Sana geliştirmek mümkün olacak sanmıyorum . Eğer bir pencere bakarsak nedeni, x t , . . . , x t + k - 1 , x t + k sayılarından hiçbirini ekarte edemezsiniznlogkxt,...,xt+k1, gelecekteki pencerenin medyanı olmaktan. Bu, herhangi bir zamanda en azkxt+k2,...,xt+k1Bir veri yapısında 2 tamsayıdır ve günlük süresinden daha kısa bir sürede güncellenmez. k2
RB

Bana senin önemsiz algoritma gibi görünüyor değil O ( n log k ) , ben yanlış bir şey ben? Ve bence bu yüzden büyük k ile problemin var.O((nk)klogk)O(nlogk)k , aksi takdirde logaritmik faktör pratik uygulamalarda hiçbir şey değildir, ayrıca bu algoritmada gizli büyük bir sabit yoktur.
Saeed,

@Saeed: Önemsiz algoritmada, öğeleri tek tek işler; adımında , arama ağacına x i eklersiniz ( i > k ise ) ayrıca x i - k'yi arama ağacından kaldırırsınız . Bu , her biri O ( log k ) zaman alan n adımdır . ixii>kxiknO(logk)
Jukka Suomela

Yani sıradan bir arama ağacınız değil, dengeli bir arama ağacınız var mı?
Saeed

1
@ Saeed: Lütfen kıyaslama ölçütlerimde medyanları bulmaya çalışmadığımı unutmayın. I just did eklemeleri ve n boyutu bir arama ağacında silmeleri k ve bu işlemler almaya garantilidir O ( log k )nnkO(logk) zamanı. Arama ağacı işlemlerinin uygulamada sıralamada kıyasla çok yavaş olduğunu kabul etmeniz yeterlidir. Dengeli bir arama ağacına öğeler ekleyerek çalışan bir sıralama algoritması yazmaya çalışırsanız bunu kolayca göreceksiniz - kesinlikle zamanında çalışır, ancak uygulamada gülünç derecede yavaşlar ve çok fazla zaman harcar Hafıza O(nlogn)
Jukka Suomela

Yanıtlar:


32

İşte sıralamadan daha düşük bir sınır. Bir giriş seti Verilen uzunluğunun n sıralanmasını, senin medyan problemi oluşan çalışan bir girdiyi oluşturmak n - 1 minimum daha küçük bir sayı kopyalarını S ardından, S kendisi daha sonra n - 1 den çok sayıda kopya daha büyük S maksimum , ve k = 2 n - 1 olarak ayarlayın . Bu girişin çalışan medyanları S'nin sıralanmış sırasına aynıdır.Snn1SSn1Sk=2n1S .

Bu yüzden bir karşılaştırma modelinde zamanı gereklidir. Muhtemelen girişleriniz tamsayılarsa ve tamsayı sıralama algoritmaları kullanıyorsanız, daha iyisini yapabilirsiniz.Ω(nlogn)


6
Bu cevap, gerçekten de muhabbetin de geçerli olup olmadığını merak etmeme neden olur: verimli bir sıralama algoritması göz önüne alındığında, etkin bir çalışan medyan algoritması elde edilir mi? (Örneğin, verimli bir tamsayı sıralama algoritması, tamsayılar için etkin bir çalışan medyan algoritması anlamına mı geliyor? Yoksa bir IO-verimli sıralama algoritması, IO-verimli çalışan medyan algoritması sağlıyor mu?)
Jukka Suomela

1
Cevabınız için bir kez daha teşekkür ederim, bu gerçekten beni doğru yola koydu ve sıralama tabanlı medyan filtre algoritması için ilham verdi! Sonunda 1991'de temelde burada verdiklerinizle aynı argümanı sunan bir makale bulabildim ve Pat Morin 2005'ten itibaren ilgili bir yazıya işaret etti; refs bakın. [6] ve [9] burada .
Jukka Suomela

9

Düzenleme: Bu algoritma şimdi burada sunulmuştur: http://arxiv.org/abs/1406.1717


Evet, bu sorunu çözmek için aşağıdaki işlemleri yapmanız yeterlidir:

  • Sıralama vektörler, her birin/k elementleri.k
  • Doğrusal zaman sonrası işleme yapın.

Çok kabaca, fikir şudur:

  • Her ikisi de k elementli iki bitişik giriş bloğu, ve b'yi göz önüne alın ; elemanlar olsun bir 1 , bir 2 , . . . , Bir k ve b 1 , b , 2 , . . . , B k girdi vektörü içerisinde geçiş sırasına göre xabka1,a2,...,akb1,b2,...,bkx .
  • Bu blokları sıralayın ve blok içindeki her bir elemanın sırasını öğrenin.
  • ve b vektörlerini selefi / ardışık işaretçilerle arttırın, böylece imleç zincirlerini takip ederek elemanları artan bir sırayla geçebiliriz. Kadar inşa ettiğimiz bu şekilde iki kat listeler bağlantılı bir ' ve b ' .abab
  • Tek tek, bağlantılı liste tüm unsurları silmek görünümü ters sırasında, b k , b , k - 1 , . . . , b 1 . Ne zaman bir öğeyi silersek, silme sırasındaki halefi ve öncülü ne olduğunu hatırla .bbk,bk1,...,b1
  • Şimdi korumak "medyan işaretçileri" ve q o listelere nokta bir ' ve b ' , sırasıyla. Initialise s orta noktasına bir " ve başlatma işlemini q boş liste kuyruğuna b ' .pqabpaqb
  • Her biri için :i

    • Sil listesinden a ' (bu Ç ( 1 ) sefer, sadece bağlantılı listeden silin). Bir i'yi , p'den önce mi yoksa sonra mı sildiğimizi görmek için p ile gösterilen elemanla karşılaştırın .aiaO(1)aipp
    • Put bi back to list b in its original position (this is O(1) time, we memorised the predecessor and successor of bi). Compare bi with the element pointed by q to see if we added the element before or after q.
    • Update pointers p and q so that the median of the joined list ab is either at p or at q. (This is O(1) time, just follow the linked lists one or two steps to fix everything. We will keep track of how many items are before/after p and q in each list, and we will maintain the invariant that both p and q point to elements that are as close to the median as possible.)

The linked lists are just k-element arrays of indexes, so they are lightweight (except that the locality of memory access is poor).


Here is a sample implementation and benchmarks:

Here is a plot of running times (for n2106):

  • Blue = sorting + post-processing, O(nlogk).
  • Green = maintain two heaps, O(nlogk), implementation from https://github.com/craffel/median-filter
  • Red = maintain two search trees, O(nlogk).
  • Black = maintain a sorted vector, O(nk).
  • X axis = window size (k/2).
  • Y axis = running time in seconds.
  • Data = 32-bit integers and random 64-bit integers, from various distributions.

running times


3

Given David's bound it's unlikely you can do better worst case, but there are better output sensitive algorithms. Specifically, if m in the number of medians in the result, we can solve the problem in time O(nlogm+mlogn).

To do this, replace the balanced binary tree with a balanced binary tree consisting of only those elements that were medians in the past, plus two Fibonacci heaps in between each pair of previous medians (one for each direction), plus counts so that we can locate which Fibonacci heap contains a particular element in the order. Don't bother ever deleting elements. When we insert a new element, we can update our data structure in O(logm) time. If the new counts indicate that the median is in one of the Fibonacci heaps, it takes an additional O(logn) to pull the new median out. This O(logn) charge occurs only once per median.

If there was a clean way to delete elements without damaging the nice Fibonacci heap complexity, we'd get down to O(nlogm+mlogk), but I'm not sure if this is possible.


Oops, this doesn't work as written, since if you don't delete elements the counts won't reflect the new window. I'm not sure if it can be fixed, but I will leave the answer in case there is a way.
Geoffrey Irving

So I think this algorithm may in fact take O(nlogm) if you delete nodes from the Fibonacci heaps, since the Fibonacci heap depth increases only when delete-min is called. Does anyone know nice bounds on Fibonacci heap complexity taking the number of delete-min calls into account?
Geoffrey Irving

side note: Question is not clear, underling data structure is not defined, we just know something very vague. how do you want improve something that you don't know what it is? how do you want compare your approach?
Saeed

1
I apologize for the incomplete work. I've asked the concrete question needed to fix this answer here: cstheory.stackexchange.com/questions/21778/…. If you think it's appropriate I can remove this answer until the secondary question is resolved.
Geoffrey Irving
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.