Menambah-kunci dan mengurangi-kunci dalam tumpukan-min biner

16

Dalam banyak diskusi tentang tumpukan biner, biasanya hanya kunci-menurun terdaftar sebagai operasi yang didukung untuk tumpukan-min. Sebagai contoh, CLR bab 6.1 dan halaman wikipedia ini . Mengapa tidak menambah kunci yang biasanya terdaftar untuk min-heap? Saya membayangkan adalah mungkin untuk melakukan itu dalam O (tinggi) dengan secara iteratif menukar elemen yang meningkat (x) dengan minimum anak-anaknya, sampai tidak ada anak-anaknya yang lebih besar dari x.

misalnya

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;
   }   
}

Apakah hal di atas benar? Jika tidak, mengapa? Jika ya, mengapa tidak menambahkan kunci terdaftar untuk min-heap?

GatotPujo
sumber
1
Setelah membaca semua jawaban, saya katakan, ini adalah penghilangan yang aneh, mungkin disebabkan oleh penggunaan min-heap yang pertama kali secara historis dalam algoritma Dijkstra.
maaartinus
3
Anda tentu saja selalu dapat menerapkan tombol-naik menggunakan delete diikuti oleh sisipan, dan delete itu sendiri dapat diimplementasikan sebagai kunci-menurun (ke -∞) diikuti oleh delete-min.
davmac
Komentar @maaartinus adalah jawaban yang benar.
maks.

Jawaban:

6

Algoritma yang Anda sarankan hanyalah heapify. Dan memang - jika Anda meningkatkan nilai elemen dalam min-heap, dan kemudian heapify subtree-nya, maka Anda akan berakhir dengan min-heap legal.

Shaull
sumber
maka tidak mengapa CLR atau daftar Wikipedia meningkatkan kunci untuk menjadi operasi yang didukung? Agak menyesatkan saya untuk berpikir bahwa itu tidak mungkin dalam min-heap
GatotPujo
Saya setuju bahwa itu menyesatkan, tetapi saya tidak melihat kesalahan dalam algoritma.
Shaull
5

Alasan bahwa operasi Anda tidak terdaftar, adalah bahwa seseorang tidak hanya tertarik pada semua operasi yang dapat dengan mudah diimplementasikan menggunakan struktur data tertentu, tetapi sebaliknya. Dengan serangkaian operasi, cara apa yang paling efisien (dalam hal ruang dan waktu) untuk mengimplementasikan operasi ini. (Tapi saya menambahkan lebih banyak ke ini nanti)

Biner tumpukan menerapkan antrian prioritas struktur data abstrak, yang meminta operasi is_empty, add_element (kunci dengan prioritasnya), find_min, dan delete_min. Antrian yang lebih maju juga memungkinkan seseorang untuk mengurangi prioritas kunci (dalam min_heap) atau bahkan meningkatkannya. Bahkan, Anda telah memberikan implementasi.

Dua komentar. Operasi Anda digunakan dalam fungsi heapify, yang secara efisien membangun heap dari array. Dalam heapify operasi Anda diulangi (mulai dari kunci terakhir).

Kemudian, yang paling penting, kode Anda menggunakan posisi node. Untuk antrian prioritas struktur data murni yang curang. Struktur data itu meminta untuk melakukan operasi tertentu yang diberi kunci. Jadi untuk mengurangi atau menambah prioritas suatu elemen, Anda harus terlebih dahulu menemukannya. Saya pikir itu adalah alasan utama tidak terdaftar.

Hendrik Jan
sumber
1
Terima kasih untuk penjelasannya. Namun, pada kunci penurunan CLR juga memiliki posisi sebagai simpul sebagai parameter.
GatotPujo
Kamu benar. Saya tidak bisa menemukan alasan asimetri ini dalam definisi antrian Prioritas di Sect.6.5 dari CLRS. Catatan peningkatan kunci tidak digunakan dalam Heapsort, aplikasi dari bab ini. Tampaknya asimetri antara kenaikan dan penurunan hanya terkait dengan cara struktur data digunakan dalam algoritma Dijkstra misalnya. Di sana (menggunakan min-heap) beberapa node yang dipilih mungkin menjadi lebih mendesak dan dipindahkan 'naik' di heap.
Hendrik Jan
0

Saya pikir hal pertama yang perlu dipertimbangkan adalah operasi apa yang didukung?

Apakah "memasukkan nilai dengan kunci tetap tertentu" (mis. Untuk kunci yang diambil dari ranah integer, menyisipkan dengan kunci = 3) sesuai dengan operasi yang didukung untuk tumpukan min?

Tidak, karena operasi itu dapat diterapkan secara sepele dengan operasi yang didukung lebih umum. Demikian juga, memasukkan 2 elemen sekaligus dapat dilakukan dengan insertoperasi yang ada .

Di sisi lain, insertoperasi tidak dapat ditentukan selain dengan mengekspos detail implementasi. Ini hampir sama untuk operasi yang terdaftar di halaman wikipedia, heapifykecuali, yang mungkin dapat diimplementasikan dengan urutan insert.

Dengan kata lain, ada operasi dasar yang disediakan pada tipe, yang terikat erat dengan detail implementasi agar mereka dapat bekerja dengan baik, dan ada operasi lain, yang tidak mematuhi aturan itu, dan dengan demikian dapat diimplementasikan sebagai kombinasi dari yang kanonik.

Dengan mempertimbangkan definisi itu, apakah Anda berpikir bahwa peningkatan kunci dapat diimplementasikan dengan operasi lain yang didukung secara eksklusif, tanpa kehilangan kinerja? Jika demikian, maka itu bukan operasi yang didukung oleh definisi di atas, jika tidak, Anda mungkin benar.

Bisa dibilang, definisi operasi yang didukung yang saya berikan adalah milik saya, sejauh yang saya tahu. Itu tidak formal, dan karenanya harus didiskusikan (walaupun tampaknya cukup jelas bagi saya). Namun, saya akan senang jika seseorang dapat memberikan sumber yang dengan jelas dan jelas mendefinisikan apa operasi yang didukung untuk tipe data, atau setidaknya mendefinisikannya dalam istilah yang lebih baik daripada milik saya (apakah definisi yang diberikan dalam CLR? Saya tidak memiliki salinan ).

Poin kedua saya adalah bagaimana kita mendefinisikan antrian prioritas (yang merupakan raison d'être dari tumpukan biner). Apakah increase_keyoperasi yang diperlukan untuk tipe data itu, yaitu untuk penggunaan yang tepat?

Seperti yang Anda lihat sudut saya adalah tentang definisi. Saya tidak benar-benar memberikan jawaban untuk pertanyaan Anda, hanya beberapa petunjuk, jadi penyempurnaan disambut.

didierc
sumber
1
contoh penggunaan case dapat jika saya ingin mempertahankan antrian prioritas objek berdasarkan paling baru-baru ini digunakan (misalnya sehingga saya dapat menghapus objek yang paling baru digunakan dengan mudah). Saya bisa menggunakan min-heap dengan tanggal akses terakhir sebagai kuncinya. Jika suatu objek diakses, kuncinya perlu ditingkatkan.
GatotPujo
Poin yang sangat bagus. Pandangan saya agak terbatas sepertinya. Sungguh, jawaban @HendrikJan membawa penjelasan yang sangat bagus.
didierc