Ekle, Sil ve Sık Kullanmayı destekleyen verimli bir veri yapısı


14

setimiz olduğunu ve nin her üyesinin bir veri ve anahtar çifti olduğunu varsayın . Aşağıdaki işlemleri destekleyecek bir veri yapısı istiyoruz:DD

  • Ekleme içine ,(d,k)D
  • Sil üye , (gerek bulmak için arama , örneğin bir üyesine noktaları ),eeeD
  • Üye döndüren MostFrequent, öyle ki içinde en sık anahtarlarından biridir (en sık anahtar benzersiz olması gerekmez olduğunu not).eDe.keyD

Bu veri yapısının etkili bir şekilde uygulanması ne olabilir?

Benim çözümüm, frekanslar tarafından önceliklendirilen tuşlar ve frekansları artı hash işlevinin, hash tablosundaki aynı anahtarla üyeleri (her parçadan diğerine işaretçilerle) aynı anahtarla eşleştirdiği bir karma tablo.

Bu , ilk iki işlem için ve üçüncü işlem için (en kötü durum çalışma süresi) verebilir .Θ(lgn)Θ(1)

Daha verimli bir çözüm olup olmadığını merak ediyorum. (veya aynı verimliliğe sahip daha basit bir çözüm?)


İsterseniz karma tablo yerine basit bir dengeli ikili arama ağacı kullanabilirsiniz.
Joe

Karma tablo çok unnessesary alanı kullanır, ben öncelik sırası öneriyoruz. Ekleme ve silme işleminde size aynı zamanda karmaşıklık verir, ancak bellek karmaşıklığı daha iyi olur.
Bartosz Przybylski

@Joe, karma tablo yerine BST kullanmak MostFrequent işlemlerini daha az verimli hale getirir, ancak bu bellek için makul bir değiş tokuş olabilir.
Kaveh

2
Yalnızca karşılaştırmalar kullanılıyorsa, öğe farklılığı sorununun alt sınırları nedeniyle Insert / MostFrequent öğesinden en az birinin itfa edilmesi gerekir . Ω(logn)
Aryabhata

1
Akış modelinde bazı ilginç yapılar da var. springerlink.com/content/t17nhd9hwwry909p
Joe

Yanıtlar:


7

Karşılaştırma tabanlı hesaplama modelinde, sıralı bir yığın yerine bir Fibonacci yığını kullanarak öncelik sırasını uygulayabilirsiniz. Bu size aşağıdaki sınırları verecektir: ekleme için itfa edilmiş zaman ve silme işlemleri için itfa edilmiş zaman.O ( log n )O(1)O(logn)

Karşılaştırma tabanlı modelden ayrılır ve anahtarların her biri bir veya daha fazla makine kelimesinde bulunan ikili dizeler olarak kabul edildiği RAM modelini benimserseniz, öncelik sıranızı uygulayabilirsiniz . Aslında, işlemi için hem hem de ekleme ve silme işlemleri için başarı elde edebilirsiniz. Thorup bunu kanıtladıO ( o(logn)O(1)O(loglogn)O(1)

Bir nevi Eğer anahtarlar zaman içinde anahtar başına, o zaman sürekli zaman ve güncellemeler bulmak-min destekleyen bir öncelik sırası uygulamak (ekleme ve silme) olabilir zaman.S ( n ) S ( n )nS(n)S(n)

Bakınız M. Thorup. Öncelik kuyrukları ve sıralama arasındaki denklik, 2002. Proc. FOCS 2002

Gösterildiği gibi beklenen zamanı ve doğrusal alanı sıralayabildiğimiz içinO(nloglogn)

Y. Han ve M. Thorup. beklenen zamanda ve doğrusal alanda tamsayı sıralama . Proc. FOCS 2002O(nloglogn)

sınır kanıtlanmıştır.


1

Bunların tümünü beklenen amortisman süresinde yapabilirsiniz. Temel hile, öncelik sırasının tam gücüne ihtiyacımız olmamasıdır, çünkü anahtar sıklığı her ekleme veya silme sırasında sadece 1 oranında değişir.O(1)

Aşağıdaki çözümüm, gerçekten bu durumda iyi sonuç veren "verimsiz" öncelik kuyruğuna sahip çözümünüzdür: Çift bağlantılı anahtar listesi olarak uygulanan bir maksimum öncelik kuyruğunda O (1) insertMin, deleteMax, removeFromBucket ve increaseKey.


Her bir Kova'nın boş olmayan bir anahtar kümesi (bir Kohort diyeceğim) ve pozitif bir tamsayı (ValCount diyeceğim) olduğu çift bağlantılı bir Kova listesi bulundurun. Bir Kova b'de, b Kohortundaki her k tuşu, bakımını yaptığınız sette onunla ilişkilendirilmiş aynı sayıda benzersiz değere sahiptir. Örneğin, kümenizde tek harflerin tuşların ve meyvelerin olduğu çiftler (a, elma), (a, avokado), (b, muz), (c, salatalık), (d, ejderha meyvesi) varsa değerleri, o zaman iki Kova olurdu: Bir Kova 2 ValCount ve sadece bir anahtardan oluşan bir Kohort olurdu: a. Diğer Bölüm 1 ValCount değerine ve b, c ve d üç anahtarından oluşan bir Kohort'a sahip olacaktır.

Çifte bağlantılı Kova listesi ValCount tarafından sipariş edilmelidir. Listenin başını ve kuyruğunu zamanında bulabilmemiz ve komşularını tanıyorsak zamanında yeni bir Kovaya ekleyebilmemiz önemlidir . Beklenmedik bir şekilde, BucketList Kovaları listesini arayacağım.O ( 1 )O(1)O(1)

BucketList'e ek olarak, ValueBuckets için karma eşleme anahtarları olan bir SetMap'e ihtiyacımız olacak. ValueBucket, ValueSet (boş olmayan bir karma değer kümesi) ve bir Kovaya null olmayan bir işaretçi içeren bir çifttir. K anahtarıyla ilişkilendirilmiş ValueSet, k ile ilişkilendirilmiş tüm benzersiz değerleri içerir. Bir ValueSet ile ilişkili Bucket işaretçisi, ValueSet'in boyutuna eşit bir Kohort'a sahiptir. SetMap içinde bir k anahtarıyla ilişkilendirilen Bucket, BucketList'teki k anahtarıyla da ilişkilendirilir.

C ++ dilinde:

struct Bucket {
    unsigned ValCount;
    unordered_set<Key> Cohort;
    Bucket * heavier;
    Bucket * lighter;
};
Bucket * BucketListHead;
Bucket * BucketListTail;

struct ValueBucket {
  unordered_set<Value> ValueSet;
  Bucket * bucket;
};
unordered_map<Key, ValueBucket> SetMap;

Bir maksimum frekans anahtar / değer çifti bulmak için, BucketList'in başına bakmamız, Kohort'ta bir anahtar bulmamız, SetMap'te bu anahtarı bulmamız ve ValueBucket'in ValueSet'inde bir değer bulmamız gerekir. (Vay be!)

Anahtar / değer çiftlerini eklemek ve silmek daha zordur.

Bir anahtar / değer çiftini eklemek veya silmek için, önce bunu SetMap'e ekler veya sileriz. Bu değişikliği yapmak için bakmamız gereken tek Kova, Kepçenin içinde bulunduğu anahtarın hemen komşuları olacak. Burada birkaç durum var ve muhtemelen tam olarak yazılmaya değmezler, ama mutlu olurum hala sorun yaşıyorsanız ayrıntılandırmak için.


Teşekkürler. Aslında bir çözüm için benzer bir fikrimiz vardı, ama bununla ilgili bir sorun vardı. Şu anda hatırlamadığım için sorunun ne olduğunu kontrol etmeliyim. Önümüzdeki hafta, çözümümüzün probleminden kaçınıp kaçınmadığını görmek için bunu daha dikkatli kontrol edeceğim.
Kaveh

İşte benim çözümüm hakkında düşünmenin başka bir yolu: gerçekten bu durumda iyi sonuç veren "verimsiz" öncelik kuyruğuna sahip çözümünüz. Çift bağlantılı anahtar listesi olarak uygulanan bir maksimum öncelik kuyruğunda O (1) insertMin, deleteMax, removeFromBucket ve boostKey bulunur.
jbapple

ValueBuckets için anahtarlardan eşlemeyi korumanın en etkili yolu (en kötü durumda) muhtemelen bir arama ağacıdır.
Raphael

Raphael - Ne elde ettiğinden emin değilim. Karma tabloların pratikte pahalı olduğunu mu yoksa en kötü durumda performanslarının kötü olduğunu mu söylüyorsunuz, yoksa üçüncü bir şey mi?
Ocak'ta jbapple

-3

En kötü durum karmaşıklığı

Ekle :O(1)

Bul-dk :O(1)

Azaltma tuşu :O(1)

Sil :O(loglogn)

Boşluk :O(n)

Kanıt

TEOREMİ 1. Bir öncelik sırası uygulayabilir, bu aralıktaki şifreler tam sayı n destekleyen doğrusal uzayda [0,N) bulmalarına-min , ekleme , ve des-anahtarı sabit zaman ve silme içinde saat.O(log log min{n,N})

Hangi kombinasyonu ile kurulmuştur:

LEMMA 3. Let olarak τ(n,N) silme için kadar bir öncelik sırası zaman aralığında tamsayılar destek elemanını ve dek-anahtarı sabit zamanda. Sonra . Bu, amortismana tabi tutulup edilmediğini veya en kötü durumda olup olmadığını gösterir .n [ 0 , N ) τ ( n , N ) τ ( N , N ) τ n[0,N) τ(n,N)τ(N,N)τ

ve:

TEOREMİ 6. teoremi 6. Biz ile bir öncelik sırası uygulayabilir aralığında şifreler tamsayıdır doğrusal bir alanda destek bulmalarına-min , sokma ve dek-anahtar ve sabit zamanda, silme olarak rütbe anahtarının zamanı .[ 0 , N ) O ( 1 + l o g l o g n - l o g l o g q ) qn[0,N)O(1+log log nlog log q)q

Referans

Thorup, Mikkel. “Sabit Zamanlı Azaltılmış Anahtar ve Tek Kaynaklı En Kısa Yollar Sorunu ile Tamsayı Öncelik Kuyrukları.” Otuz Beşinci Yıllık ACM Bilgi İşlem Teorisi Sempozyumu Bildiriler Kitabı, 149-158. STOC '03. New York, NY, ABD: ACM, 2003.


Tüm öncelik kuyruklarında 'get-min' ve 'extract-min' i destekleyen bir yapıya 'get-max' ve 'extract-max' destekleyen bir yapıya geçmenin önemsiz olduğunu unutmayın.
AT

Ping ...: @Kaveh
AT
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.