Heap vs Binary Search Tree (BST)


169

ฮีปและ BST แตกต่างกันอย่างไร

เมื่อใดจึงควรใช้ฮีปและเมื่อใช้ BST

ถ้าคุณต้องการที่จะได้รับองค์ประกอบในการเรียงลำดับ BST จะดีกว่ากอง?


13
คำถามนี้ดูเหมือนจะไม่เป็นหัวข้อเพราะเป็นเรื่องเกี่ยวกับวิทยาการคอมพิวเตอร์และควรถูกถามใน cs.stackexchange.com
Flow

3
@ กระแสถูกถามที่นั่น: cs.stackexchange.com/questions/27860/…
Ciro Santilli 郝海东冠状病病六四事件法轮功

3
ฉันรู้สึกว่ามันเกี่ยวข้องกับทั้งการแลกเปลี่ยนสแต็กและสแต็คล้น ดังนั้นการได้มาที่นี่ก็เป็นเรื่องดี
Azizbro

คำตอบ:


191

สรุป

          Type      BST (*)   Heap
Insert    average   log(n)    1
Insert    worst     log(n)    log(n) or n (***)
Find any  worst     log(n)    n
Find max  worst     1 (**)    1
Create    worst     n log(n)  n
Delete    worst     log(n)    log(n)

เวลาเฉลี่ยทั้งหมดในตารางนี้เท่ากับเวลาที่แย่ที่สุดยกเว้นการแทรก

  • *: ทุกที่ในคำตอบนี้ BST == สมดุล BST เนื่องจากความไม่สมดุลจะดูด asymptotically
  • **: การใช้การดัดแปลงเล็กน้อยอธิบายในคำตอบนี้
  • ***: log(n)สำหรับทรีของตัวชี้ฮีปnสำหรับฮีปอาร์เรย์แบบไดนามิก

ข้อดีของไบนารีฮีปผ่าน BST

  • แทรกเวลาเฉลี่ยเป็นกองไบนารีO(1)สำหรับ BST O(log(n))เป็น นี่คือคุณสมบัตินักฆ่าของกอง

    นอกจากนี้ยังมีฮีปอื่น ๆ ที่มีค่าเสื่อมราคาO(1) (แข็งแกร่งขึ้น) เช่นFibonacci Heapและแม้แต่กรณีที่เลวร้ายที่สุดเช่นคิว Brodalถึงแม้ว่ามันอาจจะไม่สามารถนำไปใช้ได้จริงเพราะประสิทธิภาพที่ไม่ใช่เชิงเส้นประสาท : ฟีโบนัชชีฮีปหรือคิว Brodal ใช้ในทางปฏิบัติหรือไม่?

  • สามารถใช้ไบนารีฮีปได้อย่างมีประสิทธิภาพที่ด้านบนของอาร์เรย์แบบไดนามิกหรือแผนภูมิแบบอิงพอยน์เตอร์, ต้นไม้ BST เท่านั้น ดังนั้นสำหรับฮีปเราสามารถเลือกการปรับใช้อาเรย์ที่มีประสิทธิภาพมากขึ้นถ้าเราสามารถจ่ายค่าเวลาในการปรับขนาดได้เป็นครั้งคราว

  • สร้างกองไบนารีเป็นO(n)กรณีที่เลวร้ายที่สุด , O(n log(n))สำหรับ BST

ข้อได้เปรียบของ BST มากกว่าไบนารีฮีป

  • O(log(n))ค้นหาสำหรับองค์ประกอบโดยพลการเป็น นี่คือคุณสมบัตินักฆ่าของ BST

    สำหรับกองมันเป็นโดยทั่วไปยกเว้นสำหรับองค์ประกอบที่ใหญ่ที่สุดซึ่งเป็นO(n)O(1)

ข้อได้เปรียบ "เท็จ" ของกองมากกว่า BST

  • กองคือO(1)จะหา max, O(log(n))BST

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

    ที่จริงแล้วนี่เป็นข้อ จำกัดของฮีปเมื่อเปรียบเทียบกับ BST: การค้นหาที่มีประสิทธิภาพเพียงอย่างเดียวคือสำหรับองค์ประกอบที่ใหญ่ที่สุด

ค่าเฉลี่ยของการแทรกฮีปไบนารีคือ O(1)

แหล่งที่มา:

อาร์กิวเมนต์ที่ใช้งานง่าย:

  • ระดับต้นไม้ด้านล่างมีองค์ประกอบมากกว่าระดับบนสุดอย่างทวีคูณดังนั้นองค์ประกอบใหม่จึงเกือบจะแน่นอนที่จะไปที่ด้านล่าง
  • การแทรกฮีปเริ่มจากด้านล่าง BST ต้องเริ่มจากด้านบน

ใน binary heap การเพิ่มค่าที่ดัชนีที่กำหนดนั้นก็O(1)เป็นเช่นเดียวกัน แต่ถ้าคุณต้องการทำเช่นนั้นเป็นไปได้ว่าคุณต้องการเก็บดัชนีพิเศษล่าสุดเกี่ยวกับการดำเนินการฮีปวิธีการดำเนินการลดคีย์ O (บันทึก) สำหรับคิวลำดับความสำคัญขั้นต่ำ เช่น Dijkstra เป็นไปได้โดยไม่มีค่าใช้จ่ายเพิ่มเติม

ไลบรารีมาตรฐาน GCC C ++ แทรกมาตรฐานในฮาร์ดแวร์จริง

ฉันเปรียบเทียบ C + + std::set( ต้นไม้สีแดง - ดำ BST ) และstd::priority_queue( ไดนามิกอาร์เรย์ฮีป ) แทรกเพื่อดูว่าฉันถูกเกี่ยวกับเวลาแทรกและนี่คือสิ่งที่ฉันได้รับ:

ป้อนคำอธิบายรูปภาพที่นี่

ชัดเจน:

  • เวลาแทรกฮีปเป็นค่าคงที่โดยทั่วไป

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

    กราฟที่ซูมไม่รวมถึงการปรับขนาดของอาเรย์เท่านั้นและแสดงให้เห็นว่าเม็ดมีดเกือบทั้งหมดอยู่ในระดับต่ำกว่า 25 นาโนวินาที

  • BST เป็นลอการิทึม เม็ดมีดทั้งหมดจะช้ากว่าเม็ดมีดทั่วไปมาก

  • การวิเคราะห์รายละเอียด BST vs hashmap ที่: โครงสร้างข้อมูลใดอยู่ใน std :: map ใน C ++?

ไลบรารีมาตรฐาน GCC C ++ แทรกมาตรฐานใน gem5

gem5m5 dumpstatsเป็นโปรแกรมจำลองระบบเต็มรูปแบบและดังนั้นจึงยังมีนาฬิกาที่ถูกต้องเพียบด้วยกับ ดังนั้นฉันจึงลองใช้มันเพื่อประเมินการกำหนดเวลาสำหรับเม็ดมีดแต่ละใบ

ป้อนคำอธิบายรูปภาพที่นี่

การตีความ:

  • กองยังคงไม่เปลี่ยนแปลง แต่ตอนนี้เราเห็นรายละเอียดเพิ่มเติมว่ามีเพียงไม่กี่บรรทัดและแต่ละบรรทัดที่สูงขึ้นจะกระจัดกระจายมากขึ้น

    สิ่งนี้จะต้องสอดคล้องกับเวลาในการเข้าถึงหน่วยความจำที่ทำได้สำหรับเม็ดมีดที่สูงขึ้นและสูงขึ้น

  • สิ่งที่ต้องทำฉันไม่สามารถตีความ BST อย่างเต็มที่เพราะมันไม่ได้ดูลอการิทึมและค่อนข้างคงที่

    ด้วยรายละเอียดที่ยิ่งใหญ่กว่านี้ แต่เราสามารถเห็นได้ว่ามีเส้นที่แตกต่างกันสองสามอัน แต่ฉันไม่แน่ใจว่ามันหมายถึงอะไร: ฉันคาดว่าบรรทัดล่างจะบางกว่าเนื่องจากเราแทรกด้านบนสุด

เทียบกับเรื่องนี้ติดตั้ง Buildrootบน aarch64 CPU HPI

BST ไม่สามารถนำไปใช้อย่างมีประสิทธิภาพในอาเรย์

การดำเนินการฮีปจำเป็นต้องทำให้ฟองขึ้นหรือลงที่กิ่งต้นไม้เดียวดังนั้นค่าเฉลี่ยของO(log(n))กรณีที่เลวร้ายที่สุดO(1)

การรักษาความสมดุล BST นั้นต้องใช้การหมุนต้นไม้ซึ่งสามารถเปลี่ยนองค์ประกอบยอดนิยมสำหรับอีกอันหนึ่งได้และจะต้องย้ายอาร์เรย์ทั้งหมดไปรอบ ๆ ( O(n))

สามารถใช้ Heaps ได้อย่างมีประสิทธิภาพในอาเรย์

ผู้ปกครองและเด็กดัชนีสามารถคำนวณได้จากดัชนีปัจจุบันเป็นที่แสดงที่นี่

ไม่มีการดำเนินการที่สมดุลเช่น BST

ลบนาทีเป็นการดำเนินการที่น่าเป็นห่วงที่สุดเนื่องจากจะต้องเลื่อนจากบนลงล่าง แต่มันก็สามารถทำได้โดยการ "แทรกซึมลง" สาขาเดียวของกองตามที่อธิบายไว้ที่นี่ สิ่งนี้นำไปสู่กรณีที่เลวร้ายที่สุด O (บันทึก (n)) เนื่องจากฮีปมีความสมดุลที่ดีเสมอ

หากคุณกำลังแทรกโหนดเดียวสำหรับทุก ๆ โหนดที่คุณลบคุณจะเสียความได้เปรียบของการแทรกเฉลี่ยแบบ asymptotic O (1) ที่ฮีปมีให้ซึ่งการลบจะมีอิทธิพลเหนือและคุณอาจใช้ BST อย่างไรก็ตาม Dijkstra อัพเดตโหนดหลายครั้งสำหรับการลบแต่ละครั้งดังนั้นเราจึงใช้ได้

ฮีปของอาร์เรย์แบบไดนามิกเทียบกับทรีของพอยเตอร์ทริก

สามารถนำHeap ไปใช้อย่างมีประสิทธิภาพที่ด้านบนของheapตัวชี้: เป็นไปได้หรือไม่ที่จะทำให้การปรับใช้ heap แบบไบนารีบนตัวชี้มีประสิทธิภาพ?

การใช้อาเรย์แบบไดนามิกนั้นมีพื้นที่มากขึ้น สมมติว่าแต่ละองค์ประกอบของฮีปประกอบด้วยเพียงตัวชี้ไปที่struct:

  • การใช้งานทรีต้องเก็บพอยน์เตอร์สามตัวสำหรับแต่ละองค์ประกอบ: parent, child child และ right child ดังนั้นการใช้หน่วยความจำจึงเป็นตลอดเวลา4n(3 พอยน์เตอร์พอยน์เตอร์ + 1 พอยน์เตอร์struct)

    Tree BSTs ต้องการข้อมูลเพิ่มเติมเช่นสมดุลสีดำ - แดง - เนส

  • การใช้งานอาร์เรย์แบบไดนามิกอาจมีขนาด2nหลังจากเพิ่มขึ้นสองเท่า 1.5nดังนั้นโดยเฉลี่ยจะเป็นไปได้

ในทางตรงกันข้ามต้นไม้กองมีแทรกกรณีที่เลวร้ายที่สุดที่ดีกว่าเนื่องจากการคัดลอกอาร์เรย์แบบไดนามิกการสำรองเพื่อสองเท่าของขนาดใช้O(n)กรณีที่เลวร้ายที่สุดในขณะที่ต้นไม้กองเพียงแค่การจัดสรรใหม่ขนาดเล็กสำหรับแต่ละโหนด

อย่างไรก็ตามอาร์เรย์สำรองสองเท่าจะถูกO(1)ตัดจำหน่ายดังนั้นจึงพิจารณาถึงความล่าช้าสูงสุด กล่าวถึงที่นี่

ปรัชญา

  • BSTs รักษาทรัพย์สินส่วนกลางระหว่างผู้ปกครองและผู้สืบทอดทั้งหมด (เหลือน้อยกว่าใหญ่กว่า)

    โหนดบนสุดของ BST เป็นองค์ประกอบกลางซึ่งต้องการความรู้ทั่วโลกในการบำรุงรักษา (รู้จำนวนองค์ประกอบที่เล็กและใหญ่กว่า)

    สถานที่ให้บริการส่วนกลางนี้มีราคาแพงกว่าในการรักษา (แทรกบันทึก n) แต่ให้การค้นหาที่มีประสิทธิภาพมากขึ้น (ค้นหาบันทึก n)

  • กองรักษาทรัพย์สินในท้องถิ่นระหว่างผู้ปกครองและเด็กโดยตรง (ผู้ปกครอง> เด็ก)

    โหนดบนสุดของฮีปคือองค์ประกอบขนาดใหญ่ซึ่งต้องการเพียงความรู้ในท้องถิ่นในการบำรุงรักษา (การรู้จักผู้ปกครองของคุณ)

เปรียบเทียบ BST กับฮีปเทียบกับ Hashmap:

  • BST: อาจเป็นได้ทั้ง:

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

  • แฮชแผนที่: สามารถเป็นชุดที่ไม่มีการเรียงลำดับเท่านั้นไม่ใช่เครื่องคัดแยกที่มีประสิทธิภาพเนื่องจากการแฮชจะรวมการเรียงลำดับใด ๆ

รายการที่ลิงก์ทวีคูณ

รายการที่เชื่อมโยงเป็นทวีคูณสามารถเห็นได้เป็นส่วนย่อยของฮีปที่รายการแรกมีลำดับความสำคัญมากที่สุดดังนั้นให้เปรียบเทียบที่นี่ด้วย:

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

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

สิ่งนี้สามารถใช้เพื่อนำแคช LRUไปใช้ เช่นเดียวกับแอปพลิเคชันฮีปเช่น Dijkstraคุณจะต้องเก็บ hashmap เพิ่มเติมจากคีย์ไปยังโหนดที่เกี่ยวข้องของรายการเพื่อค้นหาว่าโหนดใดที่ต้องอัปเดตอย่างรวดเร็ว

เปรียบเทียบ BST ที่สมดุลต่างกัน

ถึงแม้ว่าการแทรกเชิงเส้นกำกับและค้นหาเวลาสำหรับโครงสร้างข้อมูลทั้งหมดที่จัดอยู่ในประเภท "สมดุล BSTs" ที่ฉันเคยเห็นมาแล้วนั้นเหมือนกัน BBSTs ที่แตกต่างกันมีการแลกเปลี่ยนที่แตกต่างกัน ฉันยังไม่ได้ศึกษาอย่างเต็มที่ แต่ก็เป็นการดีที่จะสรุปการแลกเปลี่ยนเหล่านี้ที่นี่:

  • สีแดงสีดำต้นไม้ ดูเหมือนจะเป็น BBST ที่ใช้กันมากที่สุดในปี 2019 เช่นที่ใช้โดย GCC 8.3.0 C ++
  • ต้นไม้ AVL ดูเหมือนจะมีความสมดุลมากกว่า BST เล็กน้อยดังนั้นจึงน่าจะดีกว่าสำหรับการค้นหาเวลาแฝงในราคาต้นทุนการค้นหาที่แพงกว่าเล็กน้อย วิกิพีเดียสรุป: "ต้นไม้ AVL มักจะถูกเปรียบเทียบกับต้นไม้สีแดง - ดำเพราะทั้งสองสนับสนุนชุดปฏิบัติการเดียวกันและใช้เวลา [เดียวกัน] สำหรับการดำเนินงานขั้นพื้นฐานสำหรับแอปพลิเคชันที่ค้นหาอย่างมากต้นไม้ AVL เร็วกว่าต้นไม้สีแดง - ดำเพราะ พวกมันมีความสมดุลที่เข้มงวดมากขึ้นเช่นเดียวกับต้นไม้สีแดง - ดำต้นไม้ AVL นั้นมีความสมดุลสูงโดยทั่วไปทั้งสองนั้นไม่ได้มีความสมดุลของน้ำหนักและ mu-balanced สำหรับ mu <1/2; นั่นคือโหนดของ sibling สามารถมีได้อย่างมหาศาล จำนวนลูกหลานที่แตกต่างกัน "
  • WAVL กระดาษเดิมกล่าวถึงข้อดีของรุ่นว่าในแง่ของขอบเขตในการปรับสมดุลการดำเนินงานและการหมุน

ดูสิ่งนี้ด้วย

คำถามที่คล้ายกันใน CS: /cs/27860/whats-the-difference-between-a-binary-search-tree-and-a-binary-heap


4
ฉัน +1 แล้ว แต่ "กระดาษ" ที่แสดงให้เห็นถึงการเพิ่มค่าเฉลี่ยของ O (1) การซ้อนฮีปไบนารีตอนนี้เป็นลิงก์ที่ตายแล้วและ "สไลด์" เพียงระบุการอ้างสิทธิ์โดยไม่มีการพิสูจน์ นอกจากนี้ฉันคิดว่ามันจะช่วยชี้แจงว่า "กรณีเฉลี่ย" ที่นี่หมายถึงค่าเฉลี่ยที่สมมติว่าค่าที่แทรกมานั้นมาจากการแจกแจงบางอย่างดังนั้นฉันไม่แน่ใจว่า "นักฆ่า" คุณลักษณะนี้เป็นอย่างไร
j_random_hacker

3
BST และ BST ที่สมดุลนั้นดูเหมือนว่าจะถูกใช้แทนกันได้ มันควรจะชัดเจนว่าคำตอบหมายถึง BST ที่สมดุลเพื่อหลีกเลี่ยงความสับสน
gkalpak

2
@Bulat ผมรู้สึกว่าเรากำลัง digressing เล็ก ๆ น้อย ๆ แต่ถ้าเราต้องการทั้งสูงสุดและต่ำสุดในเวลาเดียวกันเราอาจจะเป็นปัญหาเกี่ยวกับการรักษาทั้งสองกองถ้าเราไม่ระวัง - stackoverflow.com/a/1098454/7154924 มันน่าจะดีกว่าถ้าใช้ heap สูงสุด - นาที (เนื่องจาก Atkinson et al.) ซึ่งออกแบบมาโดยเฉพาะสำหรับจุดประสงค์นี้
flow2k

1
@CiroSantilli 新疆改造中心六四事件法轮功: ฉันไม่เข้าใจว่าทำไมการดำเนินการลบของไบนารีฮีปคือ O (log n) ใช้งานได้เฉพาะในกรณีที่คุณมีตัวชี้ไปยังองค์ประกอบในฮีป แต่ในกรณีการใช้งานส่วนใหญ่คุณมีคีย์และคุณต้องค้นหาองค์ประกอบก่อนซึ่งใช้ O (n)
Ricola

5
การแทรกฮีปคือ log (n) ไม่ใช่ o (1)
Bobo

78

ฮีปจะรับประกันว่าองค์ประกอบในระดับที่สูงกว่านั้นจะใหญ่กว่า (สำหรับแม็กซ์ฮีป) หรือเล็กกว่า (สำหรับมิน - ฮีป) กว่าองค์ประกอบในระดับที่ต่ำกว่าในขณะที่ BST รับประกันคำสั่ง (จาก "ซ้าย" ถึง "ขวา") ถ้าคุณต้องการเรียงองค์ประกอบไปด้วย BST


8
"ฮีพเพียงแค่รับประกันว่าองค์ประกอบในระดับที่สูงกว่าจะสูงกว่า (สำหรับ max-heap) หรือเล็กกว่า (สำหรับ min-heap) กว่าองค์ประกอบในระดับที่ต่ำกว่า ... " - ฮีปไม่บังคับใช้สิ่งนี้ต่อระดับแต่เฉพาะในแม่และลูก โซ่. [1, 5, 9, 7, 15, 10, 11]แสดงถึง min-heap ที่ถูกต้อง แต่7ในระดับ 3 มีขนาดเล็กกว่า9ระดับ 2 สำหรับการสร้างภาพข้อมูลให้ดูตัวอย่างเช่น25และ19องค์ประกอบในภาพ Wikipedia สำหรับตัวอย่าง (โปรดทราบว่าความสัมพันธ์ที่ไม่เท่าเทียมกันระหว่างองค์ประกอบนั้นไม่เข้มงวดเนื่องจากองค์ประกอบไม่จำเป็นต้องมีความซ้ำกัน)
Daniel Andersson

ขออภัยที่มาช้า แต่ฉันต้องการความชัดเจน หาก Binary Heap ถูกเรียงลำดับดังนั้นกรณีที่แย่ที่สุดสำหรับการค้นหาคือ log n ที่ถูกต้อง ดังนั้นในกรณีนั้นจะมีการจัดเรียง Baps Heaps ที่ดีกว่า Binary Search Trees (Red-Black BST) ขอบคุณ
กฤษณะ

50

เมื่อใดจึงควรใช้ฮีปและเมื่อใช้ BST

ฮีปดีกว่าที่ findMin / findMax ( O(1)) ในขณะที่ BST นั้นดีในการค้นหาทั้งหมด ( O(logN)) ส่วนแทรกO(logN)สำหรับทั้งสองโครงสร้าง หากคุณสนใจเกี่ยวกับ findMin / findMax (เช่นลำดับความสำคัญที่เกี่ยวข้อง) ให้ไปกับ heap ถ้าคุณต้องการเรียงทุกอย่างไปด้วย BST

สองสามสไลด์แรกจากที่นี่อธิบายสิ่งต่าง ๆ อย่างชัดเจน


3
ในขณะที่การแทรกเป็นลอการิทึมสำหรับทั้งสองกรณีที่เลวร้ายที่สุดการแทรกฮีปเฉลี่ยใช้เวลาคงที่ (เนื่องจากส่วนใหญ่ขององค์ประกอบที่มีอยู่ด้านล่างในกรณีส่วนใหญ่องค์ประกอบใหม่จะมีฟองหนึ่งหรือสองระดับถ้าที่ทั้งหมด.)
johncip

1
@xysun ฉันคิดว่า BST ดีกว่าใน findMin & findMax stackoverflow.com/a/27074221/764592
Yeo

2
@Yeo: กองจะดีกว่าสำหรับ findMin xor findMax หากคุณต้องการทั้งสองอย่าง BST จะดีกว่า
Mooing Duck

1
ฉันคิดว่านี่เป็นเพียงความเข้าใจผิดที่พบบ่อย ต้นไม้ไบนารีสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อค้นหา min และ max ตามที่ Yeo ชี้ นี่เป็นข้อ จำกัดของฮีป: การค้นหาที่มีประสิทธิภาพเพียงอย่างเดียวคือขั้นต่ำหรือสูงสุด ข้อได้เปรียบที่แท้จริงของฮีปคือการแทรกเฉลี่ย O (1)ตามที่ฉันอธิบาย: stackoverflow.com/a/29548834/895245
Ciro Santilli 郝海东冠状病病六四事件法轮功

1
คำตอบของ Ciro Santilli นั้นดีกว่ามาก: stackoverflow.com/a/29548834/2873507
Vic Seedoubleyew

9

Heap สามารถทำได้findMin หรือ findMaxใน O (1) แต่ไม่ใช่ทั้งสองอย่างในโครงสร้างข้อมูลเดียวกัน อย่างไรก็ตามฉันไม่เห็นว่าฮีปจะดีกว่าใน findMin / findMax ในความเป็นจริงด้วยการปรับเปลี่ยนเล็กน้อย BST สามารถทำได้ทั้ง ในfindMin และ findMax O (1)

ใน BST ที่ถูกปรับเปลี่ยนนี้คุณจะติดตามโหนดขั้นต่ำและโหนดสูงสุดทุกครั้งที่คุณทำการดำเนินการที่อาจแก้ไขโครงสร้างข้อมูลได้ ตัวอย่างเช่นในการดำเนินการแทรกคุณสามารถตรวจสอบว่าค่า min มีค่ามากกว่าค่าที่แทรกใหม่จากนั้นกำหนดค่า min ให้กับโหนดที่เพิ่มใหม่ สามารถใช้เทคนิคเดียวกันนี้กับค่าสูงสุด ดังนั้น BST นี้มีข้อมูลเหล่านี้ซึ่งคุณสามารถเรียกดูได้ใน O (1) (เช่นเดียวกับไบนารีฮีป)

ใน BST นี้ (สมดุล BST) เมื่อคุณpop minหรือpop maxค่าขั้นต่ำถัดไปที่จะได้รับมอบหมายคือผู้สืบทอดของโหนดขั้นต่ำในขณะที่ค่าสูงสุดต่อไปที่จะกำหนดเป็นบรรพบุรุษของโหนดสูงสุด ดังนั้นมันจึงทำงานใน O (1) อย่างไรก็ตามเราจำเป็นต้องปรับสมดุลต้นไม้ดังนั้นมันจะยังคงทำงาน O (บันทึก n) (เช่นเดียวกับไบนารีฮีป)

ฉันสนใจที่จะรับฟังความคิดเห็นของคุณในความคิดเห็นด้านล่าง ขอบคุณ :)

ปรับปรุง

การอ้างอิงโยงกับคำถามที่คล้ายกันเราสามารถใช้แผนภูมิการค้นหาแบบไบนารีเพื่อจำลองการทำงานของฮีปได้หรือไม่ สำหรับการอภิปรายเพิ่มเติมเกี่ยวกับการจำลองฮีปโดยใช้ BST


ทำไมคุณไม่เห็นด้วย? คุณอยากแบ่งปันความคิดของคุณด้านล่างหรือไม่
Yeo

คุณสามารถจัดเก็บค่าสูงสุดและ / หรือค่าต่ำสุดของ BST ได้อย่างแน่นอน แต่จะเกิดอะไรขึ้นหากคุณต้องการให้ปรากฏ คุณต้องค้นหาแผนผังเพื่อลบมันจากนั้นค้นหาใหม่สำหรับ max / min ใหม่ซึ่งทั้งสองอย่างนั้นเป็นการดำเนินการ O (บันทึก n) นั่นเป็นคำสั่งเดียวกับการแทรกและการเอาออกในลำดับความสำคัญฮีปที่มีค่าคงที่แย่
Justin

@JustinLardinois ขออภัยฉันลืมไฮไลต์ในคำตอบของฉัน ใน BST เมื่อคุณทำ pop min ค่า min ขั้นต่ำถัดไปที่จะกำหนดคือตัวตายตัวแทนของโหนด min และถ้าคุณเปิดค่าสูงสุดค่าสูงสุดถัดไปที่จะกำหนดเป็นรุ่นก่อนของโหนดสูงสุด ดังนั้นมันจึงยังคงทำงานใน O (1)
Yeo

การแก้ไข: สำหรับpopMinหรือpopMaxไม่ใช่ O (1) แต่เป็น O (log n) เนื่องจากต้องเป็น Balanced BST ซึ่งจำเป็นต้องปรับสมดุลทุกการลบ ดังนั้นมันจึงเหมือนกับ binary heap popMinหรือpopMaxที่เรียกใช้ O (log n)
Yeo

2
คุณสามารถรับ min / max แรกได้ แต่การได้รับ kth min / max จะกลับไปเป็น BST ที่ซับซ้อน
ความโกลาหล

3

แผนผังการค้นหาแบบไบนารี่ใช้คำนิยาม: สำหรับทุกโหนดโหนดทางด้านซ้ายของมันจะมีค่าน้อยกว่า (คีย์) และโหนดทางด้านขวาของมันมีค่าที่มากกว่า (คีย์)

ในกรณีที่เป็นฮีปการดำเนินการของต้นไม้ไบนารีจะใช้คำจำกัดความต่อไปนี้

ถ้า A และ B เป็นโหนดโดยที่ B คือโหนดลูกของ A ดังนั้นค่า (คีย์) ของ A ต้องมากกว่าหรือเท่ากับค่า (คีย์) ของ B นั่นคือคีย์ (A) ≥คีย์ (B) )

http://wiki.answers.com/Q/Difference_between_binary_search_tree_and_heap_tree

วันนี้ฉันวิ่งแข่งกับคำถามเดียวกันเพื่อสอบและทำถูกต้อง รอยยิ้ม ... :)


"heap เป็นการนำต้นไม้ไบนารีมาใช้" - เพียงแค่ชี้ให้เห็นว่า heap เป็นต้นไม้ไบนารีชนิดหนึ่งไม่ใช่ BST
Saad

3

การใช้ BST มากกว่าฮีปอีกครั้ง เพราะความแตกต่างที่สำคัญ:

  • การค้นหาผู้สืบทอดและบรรพบุรุษใน BST จะใช้เวลา O (h) (O (บันทึก) ใน BST ที่สมดุล)
  • ในขณะที่อยู่ในกองจะใช้เวลา O (n) ในการค้นหาผู้สืบทอดหรือบรรพบุรุษขององค์ประกอบบางอย่าง

การใช้ BST เป็นฮีป : ตอนนี้ให้บอกว่าเราใช้โครงสร้างข้อมูลเพื่อเก็บเวลาลงจอดของเที่ยวบิน เราไม่สามารถกำหนดเที่ยวบินไปยังดินแดนได้หากความแตกต่างของเวลาลงจอดนั้นน้อยกว่า 'd' และสมมติว่ามีเที่ยวบินจำนวนมากถูกกำหนดให้ลงจอดในโครงสร้างข้อมูล (BST หรือ Heap)

ตอนนี้เราต้องการที่จะจัดตารางเวลาเที่ยวบินซึ่งจะจอดที่อีกที ดังนั้นเราจำเป็นต้องคำนวณความแตกต่างของtกับตัวตายตัวแทนและบรรพบุรุษ (ควร> d) ดังนั้นเราจะต้องการ BST สำหรับสิ่งนี้ซึ่งทำได้อย่างรวดเร็วเช่นใน O (logn) หากมีความสมดุล

แก้ไข:

การเรียงลำดับ BST ใช้เวลา O (n) ในการพิมพ์องค์ประกอบในลำดับที่เรียง (การข้ามผ่าน Inorder) ในขณะที่ Heap สามารถทำได้ในเวลา O (n logn) ฮีปจะแยกองค์ประกอบขั้นต่ำและทำการจัดเรียงอาเรย์อีกครั้งซึ่งจะทำการเรียงลำดับในเวลา O (n logn)


1
ใช่. มันมาจากเรียงลำดับไม่เรียงลำดับ เวลา O (n) สำหรับการแวะผ่าน inorder ของ BST ซึ่งให้ลำดับการเรียง ในขณะที่อยู่ใน Heaps คุณจะแยกองค์ประกอบขั้นต่ำและจากนั้นทำการ heapify อีกครั้งในเวลา O (log n) ดังนั้นมันจะใช้ O (n logn) เพื่อแยกองค์ประกอบ และมันจะทำให้คุณมีลำดับการเรียง
CODError

from unsorted to sorted sequence. O(n) time for inorder traversal of a BST, which gives sorted sequence.ทีนี้จากลำดับที่ไม่เรียงลำดับไปจนถึง BST ฉันไม่รู้วิธีที่อิงการเปรียบเทียบคีย์กับเวลาน้อยกว่า O (n logn) ซึ่งครอบงำ BST ไปเป็นส่วนลำดับ (ในขณะที่มีการก่อสร้างกอง O (n)) ฉันคิดว่ามันยุติธรรม (ถ้าไม่มีจุดหมาย) เพื่อระบุว่ากองอยู่ใกล้กับไม่เรียงลำดับและเรียงลำดับ BST
greybeard

สิ่งที่ฉันพยายามอธิบายที่นี่คือถ้าคุณมี BST และยังเป็นองค์ประกอบของ n = = ดังนั้นองค์ประกอบทั้งหมดสามารถพิมพ์ตามลำดับที่เรียงลำดับจากทั้งโครงสร้างข้อมูลและ BST สามารถทำได้ในเวลา O (n) (Inorder traversal ) ในขณะที่ Heap ใช้เวลา O (n logn) ฉันไม่เข้าใจสิ่งที่คุณกำลังพยายามพูดที่นี่ คุณจะบอกว่า BST จะทำให้คุณเรียงลำดับใน O (n logn) ได้อย่างไร
CODError

ฉันคิดว่าคุณกำลังพิจารณาเวลาในการสร้าง BST และกอง แต่ฉันคิดว่าคุณมีมันแล้วคุณสร้างมันขึ้นมาตามเวลาและตอนนี้คุณต้องการได้ผลลัพธ์ที่เรียงลำดับ ฉันไม่ได้รับคะแนนของคุณ?
CODError

1
แก้ไขแล้ว ... ฉันหวังว่าคุณจะพอใจในขณะนี้ p และให้ +1 ถ้าถูกต้อง
CODError

1

แทรกองค์ประกอบทั้งหมด n จากอาร์เรย์ไปยัง BST ใช้เวลา O (n logn) n elemnts ในอาเรย์สามารถแทรกเข้าไปใน heap ในเวลา O (n) ซึ่งทำให้ได้เปรียบแน่นอน


0

กองเพียงแค่รับประกันว่าองค์ประกอบในระดับที่สูงกว่าจะมากขึ้น (สำหรับ max-heap) หรือเล็กกว่า (สำหรับ min-heap) กว่าองค์ประกอบในระดับที่ต่ำกว่า

ฉันชอบคำตอบข้างต้นและใส่ความคิดเห็นของฉันเฉพาะเจาะจงมากขึ้นกับความต้องการและการใช้งานของฉัน ฉันต้องขอรายชื่อตำแหน่ง n ค้นหาระยะทางจากสถานที่แต่ละแห่งไปยังจุดเฉพาะบอกว่า (0,0) จากนั้นคืนตำแหน่ง am ที่มีระยะทางน้อยกว่า ฉันใช้ Priority Queue ซึ่งเป็น Heap สำหรับการค้นหาระยะทางและการวางกองมันเอาฉัน n (บันทึก (n)) n-location บันทึก (n) การแทรกแต่ละครั้ง จากนั้นสำหรับการหา m ด้วยระยะทางที่สั้นที่สุดมันใช้ m (log (n)) m-location บันทึก (n) การลบ heap up

ฉันถ้าจะต้องทำกับ BST มันจะเอาฉัน n (n) กรณีที่เลวร้ายที่สุดแทรก (พูดว่าค่าแรกมีขนาดเล็กมากและอื่น ๆ ทั้งหมดมาเรียงตามลำดับอีกต่อไปและอีกต่อไปและต้นไม้ครอบคลุมเด็กขวาหรือซ้ายเด็ก ในกรณีที่เล็กกว่าและเล็กกว่านาทีจะใช้เวลา O (1) แต่อีกครั้งฉันต้องสร้างความสมดุลดังนั้นจากสถานการณ์ของฉันและเหนือคำตอบสิ่งที่ฉันได้รับคือเมื่อคุณอยู่หลังจากค่าที่ต่ำสุดหรือตามลำดับความสำคัญสูงสุดไป สำหรับกอง

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