กรณีที่เลวร้ายที่สุดในการจัดเรียงที่มั่นคง?


35

ฉันมีปัญหาในการค้นหาแหล่งข้อมูลที่ดีซึ่งเป็นกรณีที่แย่ที่สุดในขั้นตอนวิธีการเรียงลำดับที่เสถียร ไม่มีใครรู้แหล่งข้อมูลที่ดีบ้างไหม?O(nlnn)

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

ตัวอย่างเช่นการเรียงลำดับที่ไร้เดียงสาเป็นกรณีที่เลวร้ายที่สุดและเสถียร แต่ใช้พื้นที่พิเศษquicksort มาตรฐานสามารถทำมั่นคงอยู่ในสถานที่ แต่ที่เลวร้ายที่สุดกรณี2) มี Heapsort อยู่กรณีที่เลวร้ายที่สุดแต่ไม่เสถียร Wikipediaมีแผนภูมิที่ดีซึ่งอัลกอริทึมการเรียงลำดับมีข้อบกพร่องใด โปรดสังเกตว่าไม่มีอัลกอริทึมการเรียงลำดับที่แสดงรายการที่มีเงื่อนไขความเสถียรทั้งสามกรณีที่เลวร้ายที่สุดและอยู่ในตำแหน่งO(nlnn)O(n)O(n2)O(nlnn)O(nlnn)

ฉันได้พบเอกสารที่เรียกว่า"การผสานการใช้งานจริงในสถานที่"โดย Katajainen, Pasanen และ Teuhola ซึ่งอ้างว่ามีกรณีที่เลวร้ายที่สุดในรูปแบบการรวมตัวแปรที่เสถียร ถ้าฉันเข้าใจผลลัพธ์ของพวกเขาถูกต้องพวกมันจะใช้การรวม (bottom-up?) ซ้ำในของอาร์เรย์และหลังของแถวและใช้ตัวที่สองเป็นพื้นที่เริ่มต้นในการรวม ฉันยังคงอ่านผ่านทางนี้ดังนั้นข้อมูลเพิ่มเติมเกี่ยวกับว่าฉันตีความผลของพวกเขาอย่างถูกต้องชื่นชมO(nlnn)141214

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

นี่เป็นความสนใจทางทฤษฎีอย่างแท้จริงและฉันไม่มีการใช้งานจริง ฉันแค่อยากจะรู้ว่าอัลกอริทึมที่มีคุณสมบัติทั้งสามนี้


มีคำถามที่คล้ายกันใน SO ที่นี่พร้อมคำตอบที่ให้การอ้างอิงที่ฉันให้ไว้ในคำถาม ฉันเชื่อว่านี่ไม่ใช่คำถามซ้ำซ้อนเนื่องจากฉันขอคำชี้แจงเพิ่มเติมเอกสารเพิ่มเติมและคำอธิบายของอัลกอริทึม
user834

1
ดูคำถามนี้ใน math.stackexchange.com
Tsuyoshi Ito

เหตุใดการเลือกเดือยใน QuickSort จึงมีวิธีที่แตกต่างกัน
svick

@svick วิธีเดียวที่ฉันรู้วิธีทำให้ QuickSort กรณีที่เลวร้ายที่สุดคือการเลือกเดือยที่ชาญฉลาดกว่าการสุ่ม วิธีที่ฉันเรียนรู้ที่จะทำคือใช้อัลกอริธึมการเลือกซึ่งใช้อัลกอริธึมมัธยฐานของมัธยฐานซึ่งทำลายเสถียรภาพ หากฉันพลาดบางสิ่งโปรดแจ้งให้เราทราบ O(nlnn)
user834

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

คำตอบ:


6

มีอัลกอริธึมหลายอย่างที่กล่าวมาข้างต้นและทั้งหมดได้รับการคิดค้นใน 30 ปีที่ผ่านมา

น่าจะเป็นสิ่งที่ดีที่สุดคือคลาสของอัลกอริทึมที่เรียกว่าBlock sortรวมถึงเวอร์ชั่น (เรียกว่า WikiSort) โดย Kim และ Kutzner ในปี 2008 มันไม่เพียง แต่มีเสถียรภาพและสมบูรณ์แบบในสถานที่ (O (1) หน่วยความจำเหนือศีรษะ ยังสามารถปรับเปลี่ยนได้และจะใช้ขั้นตอนน้อยลงในการเรียงลำดับรายการที่เรียงลำดับเกือบจะรวมไปถึงการเปรียบเทียบ O (n) ในกรณีของรายการที่เรียงลำดับแล้ว คุณสามารถค้นหาการนำไปใช้ใน C, C ++ และ Java ที่นี่: https://github.com/BonzaiThePenguin/WikiSort

สิ่งที่น่าสนใจก็คืออัลกอริธึม GrailSort (เช่น Block sort) โดย Huang และ Langston (1989-1992) ซึ่งจริง ๆ แล้วมีประสิทธิภาพเหนือกว่า WikiSort ในกรณีทดสอบหลายประเภท มีการใช้งาน C ++ ได้ที่นี่: https://github.com/Mrrl/GrailSort


8

คุณสามารถเขียนการผสานที่มีเสถียรภาพ ดูนี้สำหรับรายละเอียด ในคำพูดของผู้เขียนเอง:

อัลกอริทึมที่สวยงามในการผสาน ทดสอบในอาร์เรย์กลับด้านเพื่อทำความเข้าใจว่าการหมุนทำงานอย่างไร รู้จักเร็วที่สุดในการจัดเรียงที่มั่นคง ไม่มีความเสี่ยงในการระเบิดของสแต็ก ราคา: จำนวนการเคลื่อนไหวค่อนข้างสูง กองซ้อนยังมีราคาแพงเช่นกัน นี่คือการเรียงลำดับผสานกับการผสานที่ชาญฉลาดซึ่ง 'หมุน' อาร์เรย์ย่อย รหัสนี้คัดลอกมาจาก litteraly จากไลบรารี C ++ stl และแปลเป็นภาษาจาวา

ฉันจะไม่คัดลอกรหัสที่นี่ แต่คุณสามารถค้นหาได้ที่ลิงค์หรือโดยการตรวจสอบ C ++ STL โปรดแจ้งให้เราทราบหากคุณต้องการให้ฉันพยายามอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นที่นี่


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

Knuth จัดการเรื่องนี้ใน TAoCP เช่นกัน
กราฟิลส์

ขั้นตอนวิธีการที่คุณกล่าวถึงที่นี่เป็นที่ที่เลวร้ายที่สุดกรณี2n) cf เลย cplusplus.com/reference/algorithm/stable_sort (โดยเฉพาะความเห็นเกี่ยวกับเวลาทำงานเมื่อมีหน่วยความจำเพิ่มเติมไม่เพียงพอ) O(nln2n)
quintopia

1

โปรดใช้สิ่งนี้เป็นความคิดเห็นที่ยาวเกี่ยวกับความคิดเชิงปฏิบัติ แม้ว่านี่จะไม่ใช่คำตอบสำหรับคำถามของคุณ แต่ฉันคิดว่าคุณอาจสนใจในการสนทนา Python นี้:

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

[ ... ]

ผสานการทำงานที่อยู่ติดกันของความยาวที่ A และ B ในสถานที่เป็นเรื่องยากมาก การก่อสร้างทางทฤษฎีเป็นที่รู้จักกันว่าสามารถทำมันได้ แต่พวกเขากำลังยากเกินไปและช้าสำหรับการใช้งานจริง แต่ถ้าเรามีหน่วยความจำอุณหภูมิเท่ากับ min (A, B) มันง่าย

ที่มา: bugs.python.orgผู้แต่ง: Tim Peters

ดังนั้นดูเหมือนว่า Timsort ยังคงมีข้อได้เปรียบเหนือความเสถียรในสถานที่เวลาที่ซับซ้อนที่สุดในกรณีที่ซับซ้อนO(nlogn)

นอกจากนี้โปรดทราบว่า Timsort ทำงานได้ดีบนอาร์เรย์ที่เรียงลำดับแล้ว

ดังนั้น Python ใช้ Timsort (ซึ่งเป็น Mergesort กับ tweaks บางอย่าง) และเมื่อฉันค้นหาการใช้ Java เมื่อหลายปีก่อนมันเป็น Mergesort ด้วย (ฉันคิดว่าตอนนี้พวกเขายังใช้ Timsort ด้วย)

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