İkili bir yığın yığını içinde artış tuşu ve azaltma tuşu


17

İkili yığın ile ilgili birçok tartışmada, normalde yalnızca küçük anahtar bir min-yığın için desteklenen işlem olarak listelenir. Örneğin, CLR bölüm 6.1 ve bu wikipedia sayfası . Min. Yığın için normalde artış anahtarı neden listelenmiyor? O (yükseklik) 'de, artan elemanı (x)' in çocuklarından hiçbiri x'den büyük olana kadar çocuklarının minimumuyla tekrar tekrar değiştirilerek yapılması mümkün olduğunu düşünüyorum.

Örneğin

IncreaseKey(int pos, int newValue)
{
   heap[pos] = newValue;
   while(left(pos) < heap.Length)
   {
      int smallest = left(pos);
      if(heap[right(pos)] < heap[left(pos)])
         smallest = right(pos);
      if(heap[pos] < heap[smallest])
      { 
         swap(smallest, pos);
         pos= smallest;
      }
      else return;
   }   
}

Yukarıdakiler doğru mu? Değilse, neden? Evet ise, min-yığın için neden artış anahtarı listelenmiyor?


1
Tüm cevapları okuduktan sonra, muhtemelen Dijkstra algoritmasında tarihsel olarak ilk min-yığın kullanımından kaynaklanan garip bir ihmal olduğunu söyleyebilirim.
maaartinus

3
Tabii ki her zaman artış anahtarını bir silme ve ardından bir ekleme kullanarak uygulayabilir ve silmenin kendisi, azaltma anahtarı (-∞'a) ve ardından delete-min olarak uygulanabilir.
davmac

@maaartinus yorumu doğru cevaptır.
maksimum

Yanıtlar:


6

Önerdiğiniz algoritma basitçe heapify. Ve gerçekten - bir min-yığındaki bir öğenin değerini arttırır ve sonra alt ağacını yığınlarsanız, yasal bir min-yığınla sonuçlanırsınız.


Peki neden CLR veya Wikipedia listesi Artır tuşu desteklenen bir işlem değildir? Bir min-yığın içinde mümkün olmadığını düşünmek beni yanlış yönlendirdi
GatotPujo

Yanıltıcı olduğuna katılıyorum, ancak algoritmada herhangi bir hata görmüyorum.
Shaull

5

İşleminizin listelenmemesinin nedeni, birinin belirli bir veri yapısı kullanılarak kolayca gerçekleştirilebilecek tüm işlemlerle değil, aksine diğer yöntemle ilgilenmesidir. Bir dizi operasyon göz önüne alındığında, bu operasyonları uygulamanın en etkili yolu (yer ve zaman açısından) nedir. (Ama daha sonra buna daha fazlasını ekliyorum)

İkili yığınlar, is_empty, add_element (önceliğine sahip bir anahtar), find_min ve delete_min işlemlerini isteyen soyut veri yapısı öncelik sırasını uygular. Daha gelişmiş kuyruklar ayrıca anahtarın önceliğini (min_heap içinde) azaltmaya veya hatta artırmaya izin verir. Aslında bir uygulama yaptınız.

İki açıklama. İşleminiz, diziden bir yığın etkin bir şekilde oluşturan heapify işlevinde kullanılır. Öbek olarak işleminiz tekrarlanır (son tuştan başlayarak).

Ardından, en önemlisi, kodunuz düğümün konumunu kullanır. Saf veri yapısı için hile yapan öncelik sırası. Bu veri yapısı bir anahtar verilen belirli bir işlemi gerçekleştirmeyi ister. Bu nedenle, bir öğenin önceliğini azaltmak veya artırmak için önce onu bulmanız gerekir. Listede yer almamasının ana nedeni olduğunu düşünüyorum.


1
Açıklama için teşekkürler. Bununla birlikte, CLR azaltma tuşu, parametre olarak düğüm olarak konuma sahiptir.
GatotPujo

Haklısın. CLRS Bölüm.6.5'teki Öncelik kuyruklarının tanımında bu asimetri için bir neden bulamadım. Bu bölümün uygulanması olan Heapsort'ta artış anahtarının kullanılmadığına dikkat edin. Görünüşe göre, artış ve azalış arasındaki asimetri, veri yapısının örneğin Dijkstra algoritmasında kullanılma şekli ile ilişkili görünmektedir. Orada (bir min-yığın kullanarak) seçilen bazı düğümler daha acil hale gelebilir ve yığın içinde 'yukarı' hareket ettirilebilir.
Hendrik Jan

0

Düşünülmesi gereken ilk şey, desteklenen bir işlem nedir?

"Belirli, sabit bir anahtarla değer eklemek" (örneğin, tamsayı alanından alınan anahtarlar için, = 3 ile ekleme), min yığını için desteklenen bir işleme karşılık geliyor mu?

Hayır, çünkü bu işlem daha genel desteklenen operasyonlarla önemsiz bir şekilde uygulanabilir. Benzer şekilde, mevcut eleman ile aynı anda 2 elemanın yerleştirilmesi yapılabilir insert.

Öte yandan, insertişlem, uygulama ayrıntılarını göstermekten başka bir şekilde tanımlanamaz. Wikipedia sayfasında listelenen işlemler heapifyhariç, hemen hemen aynıdır insert.

Başka bir deyişle, tür üzerinde sağlanan ve iyi performans göstermeleri için uygulama ayrıntılarına sıkı sıkıya bağlı olan temel işlemler vardır ve bu kurala uymayan ve dolayısıyla bir kombinasyon olarak uygulanabilecek diğer işlemler de vardır. kanonik olanların.

Bu tanımı göz önünde bulundurarak, artış anahtarının performans kaybı olmadan yalnızca desteklenen diğer işlemlerle uygulanabileceğini düşünüyor musunuz? Eğer öyleyse, yukarıdaki tanım tarafından desteklenen bir işlem değildir, aksi takdirde haklı olabilirsiniz.

Muhtemelen, sağladığım desteklenen bir operasyonun tanımı bildiğim kadarıyla benim. Resmi değildir ve bu nedenle tartışmaya tabidir (her ne kadar benim için oldukça net görünse de). Ancak, birisi veri türleri için desteklenen bir işlemin ne olduğunu açık ve net bir şekilde tanımlayan veya en azından benimkinden daha iyi terimlerle tanımlayan bir kaynak sağlayabilirse memnun olurum (CLR'de verilen tanım nedir? ).

İkinci noktam, öncelik sırasını (ikili yığınların varlık nedeni) nasıl tanımlayacağımız olacak. Bu increase_keyveri tipi için, yani doğru kullanımı için gerekli bir işlem midir?

Gördüğünüz gibi benim açım sadece tanımlarla ilgili. Sorularınıza gerçekten cevap vermiyorum, sadece bazı işaretçiler, bu yüzden geliştirmeler bekliyoruz.


1
örnek kullanım durumu, en az kullanılan (örneğin en son kullanılan nesneleri kolayca silebilirim) dayalı bir nesne öncelik sırasını korumak istiyorsanız olabilir. Anahtarı olarak son erişim tarihi olan bir min-yığın kullanabilirsiniz. Bir nesneye erişilirse, anahtarının artırılması gerekir.
GatotPujo

Çok iyi bir nokta. Benim görüşüm biraz sınırlı gibi görünüyor. Gerçekten, @HendrikJan'ın cevabı çok iyi bir açıklama getiriyor.
didierc
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.