เพิ่มคีย์และคีย์ลดในไบนารีมินฮีป


16

ในการสนทนาจำนวนมากของไบนารีฮีปปกติจะมีการแสดงคีย์ลดลงเพียงคีย์ว่าเป็นการดำเนินการที่ได้รับการสนับสนุนสำหรับมินิฮีป ยกตัวอย่างเช่น CLR บทที่ 6.1 และหน้าวิกิพีเดียนี้ เหตุใดจึงไม่เพิ่มรหัสปกติสำหรับ min-heap ฉันคิดว่าเป็นไปได้ที่จะทำเช่นนั้นใน O (ความสูง) โดยการสลับองค์ประกอบที่เพิ่มขึ้น (x) ซ้ำ ๆ โดยใช้ลูกน้อยที่สุดจนกว่าจะไม่มีลูกใดของมันใหญ่กว่า x

เช่น

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

ถูกต้องหรือไม่ ถ้าไม่ทำไม ถ้าใช่ทำไมไม่เพิ่มคีย์ที่ระบุไว้สำหรับ min-heap


1
หลังจากอ่านคำตอบทั้งหมดฉันจะบอกว่ามันเป็นสิ่งที่แปลกประหลาดซึ่งอาจเกิดจากการใช้ min-heap ครั้งแรกในประวัติศาสตร์ในอัลกอริทึม Dijkstra
maaartinus

3
แน่นอนว่าคุณสามารถเพิ่มรหัสได้โดยใช้การลบตามด้วยการแทรกและการลบตัวเองสามารถนำไปใช้เป็นปุ่มลด (ถึง-∞) ตามด้วยการลบ
davmac

@maaartinus ความคิดเห็นคือคำตอบที่ถูกต้อง
สูงสุด

คำตอบ:


6

อัลกอริทึมที่คุณแนะนำคือเพียงแค่เพิ่ม และแน่นอน - ถ้าคุณเพิ่มมูลค่าขององค์ประกอบใน min-heap จากนั้น heapify ทรีย่อยของมันจากนั้นคุณจะจบลงด้วย min-heap ที่ถูกกฎหมาย


ถ้าอย่างนั้นทำไมไม่เพิ่ม CLR หรือ Wikipedia เพื่อเพิ่มการดำเนินงานที่รองรับ? มันทำให้ฉันเข้าใจผิดคิดว่ามันเป็นไปไม่ได้ในกองเล็ก ๆ
GatotPujo

ฉันยอมรับว่ามันทำให้เข้าใจผิด แต่ฉันไม่เห็นความผิดพลาดใด ๆ ในอัลกอริทึม
Shaull

5

เหตุผลที่การดำเนินการของคุณไม่อยู่ในรายการนั่นคือไม่ได้สนใจเพียงแค่การดำเนินงานทั้งหมดที่สามารถนำไปใช้งานได้ง่ายโดยใช้โครงสร้างข้อมูลบางอย่าง แต่เป็นวิธีอื่น เมื่อได้รับชุดของการดำเนินงานวิธีที่มีประสิทธิภาพมากที่สุด (ในแง่ของพื้นที่และเวลา) คือการใช้การดำเนินการเหล่านี้ (แต่ฉันเพิ่มมากขึ้นในภายหลัง)

ฮีปแบบไบนารีใช้คิวลำดับความสำคัญของโครงสร้างข้อมูลนามธรรมซึ่งขอการดำเนินการ is_empty, add_element (คีย์ที่มีลำดับความสำคัญ), find_min และ delete_min คิวขั้นสูงเพิ่มเติมอนุญาตให้หนึ่งลดลำดับความสำคัญของคีย์ (ใน min_heap) หรือเพิ่มขึ้น ในความเป็นจริงคุณได้รับการดำเนินการ

สองข้อสังเกต การทำงานของคุณถูกใช้ในฟังก์ชั่น heapify ที่สร้าง heap จากอาเรย์อย่างมีประสิทธิภาพ ในการเพิ่มประสิทธิภาพการดำเนินงานของคุณซ้ำแล้วซ้ำอีก (เริ่มจากปุ่มสุดท้าย)

ที่สำคัญที่สุดคือรหัสของคุณใช้ตำแหน่งของโหนด สำหรับคิวลำดับความสำคัญของโครงสร้างข้อมูลบริสุทธิ์ที่โกง โครงสร้างข้อมูลนั้นขอให้ดำเนินการบางอย่างให้รหัส ดังนั้นเพื่อลดหรือเพิ่มลำดับความสำคัญขององค์ประกอบคุณจะต้องค้นหาก่อน ฉันคิดว่านั่นเป็นเหตุผลหลักที่ไม่มีในรายการ


1
ขอบคุณสำหรับคำอธิบาย อย่างไรก็ตามในการลดคีย์ CLR ยังมีตำแหน่งเป็นโหนดเป็นพารามิเตอร์
GatotPujo

คุณพูดถูก ฉันไม่สามารถหาเหตุผลสำหรับความไม่สมดุลนี้ในนิยามของคิวลำดับความสำคัญใน Sect.6.5 ของ CLRS หมายเหตุ: จะไม่ใช้การเพิ่มคีย์ใน Heapsort แอปพลิเคชันของบทนี้ ดูเหมือนว่าความไม่สมดุลระหว่างการเพิ่มและการลดลงจะสัมพันธ์กับวิธีการใช้โครงสร้างข้อมูลในอัลกอริทึมของ Dijkstra เท่านั้น ที่นั่น (ใช้ min-heap) บางโหนดที่เลือกอาจมีความเร่งด่วนกว่าและถูกย้าย 'up' ใน heap
Hendrik Jan

0

ฉันคิดว่าสิ่งแรกที่ต้องพิจารณาคือการดำเนินการที่ได้รับการสนับสนุนคืออะไร

"การแทรกค่าด้วยคีย์ที่เจาะจงและแน่นอน" (เช่นสำหรับคีย์ที่นำมาจากขอบเขตจำนวนเต็มการแทรกด้วย key = 3) สอดคล้องกับการดำเนินการที่ได้รับการสนับสนุนสำหรับฮีปขั้นต่ำหรือไม่

ไม่เพราะการดำเนินการนั้นสามารถนำไปปฏิบัติได้เล็กน้อยโดยมีการดำเนินงานที่สนับสนุนทั่วไป ในทำนองเดียวกันการแทรก 2 องค์ประกอบพร้อมกันสามารถทำได้ด้วยการinsertดำเนินการที่มีอยู่

ในทางตรงกันข้ามการinsertดำเนินการไม่สามารถกำหนดเป็นอย่างอื่นได้โดยเปิดเผยรายละเอียดการใช้งาน มันค่อนข้างเหมือนกันสำหรับการดำเนินการที่ระบุไว้ในหน้าวิกิพีเดียheapifyยกเว้นซึ่งอาจมีการดำเนินการตามลำดับของinsertยกเว้นซึ่งอาจจะได้รับการดำเนินการโดยลำดับของ

กล่าวอีกนัยหนึ่งมีการดำเนินงานเบื้องต้นในประเภทซึ่งผูกพันกับรายละเอียดการนำไปปฏิบัติเพื่อให้ทำงานได้ดีและมีการดำเนินงานอื่น ๆ ที่ไม่ปฏิบัติตามกฎนั้นและอาจนำมาใช้เป็นชุดค่าผสม ของคนที่ยอมรับ

ด้วยความหมายในใจคุณคิดว่าจะสามารถใช้คีย์การเพิ่มกับการดำเนินการอื่น ๆ ที่สนับสนุนได้อย่างเต็มที่โดยไม่สูญเสียประสิทธิภาพหรือไม่ หากเป็นเช่นนั้นแสดงว่าไม่ได้รับการสนับสนุนตามข้อกำหนดข้างต้นมิฉะนั้นคุณอาจพูดถูก

ความหมายของการปฏิบัติการที่สนับสนุนที่ฉันให้นั้นเป็นของฉันเท่าที่ฉันรู้ มันไม่เป็นทางการและอยู่ภายใต้การสนทนา (แม้ว่าฉันจะค่อนข้างชัดเจนสำหรับฉัน) อย่างไรก็ตามฉันจะดีใจถ้ามีคนสามารถให้แหล่งข้อมูลที่ชัดเจนและชัดเจนว่าการดำเนินการที่สนับสนุนสำหรับประเภทข้อมูลหรืออย่างน้อยก็กำหนดไว้ในเงื่อนไขที่ดีกว่าของฉัน (เป็นคำนิยามที่กำหนดใน CLR หรือไม่ฉันไม่มีสำเนา )

จุดที่สองของฉันจะอยู่ที่วิธีที่เรากำหนดคิวลำดับความสำคัญ (ซึ่งเป็น raison d'êtreของไบนารีฮีป) การincrease_keyดำเนินการที่จำเป็นสำหรับประเภทข้อมูลนั้นคือการใช้งานที่เหมาะสม?

อย่างที่คุณเห็นมุมของฉันนั้นเกี่ยวกับคำจำกัดความ ฉันไม่ได้ให้คำตอบสำหรับคำถามของคุณจริง ๆ มีเพียงพอยน์เตอร์บางคำเท่านั้นดังนั้นจึงยินดีรับการปรับปรุง


1
กรณีการใช้งานตัวอย่างสามารถเป็นได้หากฉันต้องการรักษาลำดับความสำคัญของวัตถุตามการใช้งานน้อยที่สุด (เช่นเพื่อให้ฉันสามารถลบวัตถุที่ใช้งานน้อยที่สุดได้อย่างง่ายดาย) ฉันสามารถใช้แผนที่ขนาดเล็กที่มีวันที่เข้าถึงล่าสุดเป็นกุญแจสำคัญได้ หากเข้าถึงวัตถุต้องมีการเพิ่มคีย์
GatotPujo

จุดที่ดีมาก มุมมองของฉันค่อนข้าง จำกัด จริงๆ @HendrikJan คำตอบนำเสนอคำอธิบายที่ดีมาก
didierc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.