อัลกอริทึมการเรียงลำดับใดที่ทำงานได้ดีที่สุดกับข้อมูลที่เรียงลำดับส่วนใหญ่
อัลกอริทึมการเรียงลำดับใดที่ทำงานได้ดีที่สุดกับข้อมูลที่เรียงลำดับส่วนใหญ่
คำตอบ:
จากวิธีการทางวิทยาศาสตร์อย่างมากในการรับชมภาพเคลื่อนไหว gifsฉันจะบอกว่าการเรียงลำดับแบบแทรกและแบบฟองนั้นเป็นตัวเลือกที่ดี
มีเพียงไม่กี่รายการ => INSERTION SORT
รายการส่วนใหญ่จะถูกจัดเรียงแล้ว => INSERTION SORT
มีความกังวลเกี่ยวกับสถานการณ์ที่เลวร้ายที่สุด => HEAP SORT
สนใจในผลลัพธ์เฉลี่ยที่ดี => QUICKSORT
ไอเท็มถูกดึงมาจากจักรวาลที่มีความหนาแน่นสูง => BUCKET SORT
ความปรารถนาที่จะเขียนโค้ดให้น้อยที่สุด => INSERTION SORT
Timsortคือ "การปรับตัวที่มีเสถียรภาพการผสานตามธรรมชาติ" กับ " ประสิทธิภาพเหนือธรรมชาติในหลาย ๆ ส่วนของอาร์เรย์ที่ได้รับคำสั่งบางส่วน (น้อยกว่า lg (N!) ที่จำเป็นในการเปรียบเทียบ ในตัว Pythonsort()
ได้ใช้อัลกอริทึมนี้บางครั้งเห็นได้ชัดว่ามีผลลัพธ์ที่ดี มันออกแบบมาโดยเฉพาะเพื่อตรวจจับและใช้ประโยชน์จากการเรียงลำดับบางส่วนในอินพุตซึ่งมักเกิดขึ้นในชุดข้อมูลจริง บ่อยครั้งในโลกแห่งความเป็นจริงที่การเปรียบเทียบนั้นมีราคาแพงกว่าการแลกเปลี่ยนไอเท็มในรายการเนื่องจากมักจะเป็นพอยน์เตอร์พอยน์เตอร์ซึ่งบ่อยครั้งทำให้ Timsort เป็นตัวเลือกที่ยอดเยี่ยม อย่างไรก็ตามหากคุณรู้ว่าการเปรียบเทียบของคุณมักจะถูกมาก (เช่นการเขียนโปรแกรมของเล่นเพื่อเรียงลำดับจำนวนเต็ม 32 บิต) อัลกอริทึมอื่น ๆ นั้นมีแนวโน้มที่จะทำงานได้ดีขึ้น วิธีที่ง่ายที่สุดในการใช้ประโยชน์จาก timsort คือการใช้ Python แต่เนื่องจาก Python เป็นโอเพ่นซอร์สคุณอาจยืมรหัสได้ อีกวิธีหนึ่งคำอธิบายข้างต้นมีรายละเอียดมากกว่าที่จะเขียนการใช้งานของคุณเอง
lg(n!)
การเปรียบเทียบอาเรย์เกือบเรียงลำดับทุกทางจนถึงO(n)
! | @behrooz: ไม่มีการเปรียบเทียบการจัดเรียงสามารถมีกรณีเฉลี่ยของที่ดีกว่าO(n log n)
และเป็นlg(n!)
O(n log n)
ดังนั้นกรณีที่เลวร้ายที่สุดของ Timsort จึงไม่เลวร้ายไปกว่าการเปรียบเทียบแบบอื่น ๆ นอกจากนี้กรณีที่ดีที่สุดดีกว่าหรือเท่ากับการเปรียบเทียบแบบอื่น
การเรียงลำดับการแทรกที่มีลักษณะการทำงานต่อไปนี้:
k
ในช่อง1..n
, el[k] >= el[k-1]
ตรวจสอบก่อนว่า ถ้าเป็นเช่นนั้นไปที่องค์ประกอบต่อไป (เห็นได้ชัดว่าข้ามองค์ประกอบแรก)1..k-1
เพื่อกำหนดตำแหน่งการแทรกจากนั้นให้ตรวจสอบองค์ประกอบต่างๆ (คุณอาจทำสิ่งนี้เฉพาะในกรณีk>T
ที่T
บางค่ามีค่าเกณฑ์; กับขนาดเล็กk
นี้เป็น overkill)วิธีนี้ทำให้การเปรียบเทียบจำนวนน้อยที่สุด
ลองเรียงลำดับครุ่นคิด http://en.wikipedia.org/wiki/Introsort
มันใช้ quicksort แต่มันหลีกเลี่ยงพฤติกรรมของ case ที่แย่ที่สุดที่ quicksort มีสำหรับรายการที่เรียงลำดับเกือบ
เคล็ดลับคืออัลกอริธึมการเรียงลำดับนี้จะตรวจจับกรณีที่ quicksort เข้าสู่โหมดเคสที่แย่ที่สุดและสลับไปที่การเรียงลำดับฮีพหรือการผสาน พาร์ติชั่นที่เรียงเกือบจะถูกตรวจพบโดยวิธีพาร์ติชั่นที่ไม่ใช่แบบ naiive และพาร์ติชั่นขนาดเล็กจะถูกจัดการโดยใช้การเรียงลำดับการแทรก
คุณจะได้รับสิ่งที่ดีที่สุดของอัลกอริทึมการเรียงลำดับที่สำคัญทั้งหมดสำหรับค่าใช้จ่ายของรหัสและความซับซ้อนที่มากขึ้น และคุณสามารถมั่นใจได้ว่าคุณจะไม่พบพฤติกรรมกรณีที่เลวร้ายที่สุดไม่ว่าข้อมูลของคุณจะเป็นอย่างไร
หากคุณเป็นโปรแกรมเมอร์ C ++ ให้ตรวจสอบ std :: sort algorithm มันอาจใช้การเรียงลำดับครุ่นคิดภายในแล้ว
Splaysortเป็นวิธีการเรียงลำดับที่คลุมเครือบนพื้นฐานของต้นไม้สเลย์ซึ่งเป็นต้นไม้ไบนารีที่ปรับตัวได้ Splaysort นั้นดีไม่เพียง แต่สำหรับข้อมูลที่เรียงลำดับบางส่วนเท่านั้น แต่ยังรวมถึงข้อมูลที่เรียงกลับกันบางส่วนหรือข้อมูลใด ๆ ที่มีคำสั่งที่มีอยู่ล่วงหน้า มันเป็น O (nlogn) ในกรณีทั่วไปและ O (n) ในกรณีที่ข้อมูลถูกจัดเรียงในทางใดทางหนึ่ง (ไปข้างหน้าย้อนกลับอวัยวะท่อ ฯลฯ )
ข้อได้เปรียบที่ยอดเยี่ยมมากกว่าการเรียงลำดับการแทรกคือมันจะไม่เปลี่ยนกลับไปเป็นพฤติกรรม O (n ^ 2) เมื่อข้อมูลไม่ได้ถูกจัดเรียงเลยดังนั้นคุณไม่จำเป็นต้องแน่ใจว่าข้อมูลถูกเรียงบางส่วนก่อนที่จะใช้ .
ข้อเสียของมันคือค่าใช้จ่ายเพิ่มเติมของโครงสร้างต้นไม้ที่ต้องการรวมถึงเวลาที่ต้องใช้ในการสร้างและทำลายต้นไม้สเปรย์ แต่ขึ้นอยู่กับขนาดของข้อมูลและจำนวนของการเรียงลำดับล่วงหน้าที่คุณคาดหวังค่าใช้จ่ายอาจคุ้มค่าสำหรับการเพิ่มความเร็ว
กระดาษใน splaysortถูกตีพิมพ์ในซอฟแวร์ - การปฏิบัติและประสบการณ์
แทรกหรือเรียงลำดับเปลือก!
Smoothsort ของ Dijkstra นั้นเป็นข้อมูลที่เรียงลำดับแล้ว มันเป็นตัวแปรฮีปพอร์ตที่ทำงานใน O (n lg n) กรณีที่แย่ที่สุดและ O (n) กรณีที่ดีที่สุด ฉันเขียนบทวิเคราะห์อัลกอริทึมในกรณีที่คุณอยากรู้ว่ามันทำงานอย่างไร
การรวมกันตามธรรมชาติเป็นอีกสิ่งหนึ่งที่ดีมากสำหรับเรื่องนี้ - มันเป็นตัวแปรการรวมตัวจากล่างขึ้นบนที่ทำงานโดยการจัดการอินพุตเป็นการเชื่อมต่อของช่วงเรียงที่แตกต่างกันหลายช่วงจากนั้นใช้อัลกอริทึมผสานเพื่อรวมเข้าด้วยกัน คุณทำขั้นตอนนี้ซ้ำจนกว่าจะเรียงลำดับช่วงการป้อนข้อมูลทั้งหมด สิ่งนี้จะทำงานในเวลา O (n) ถ้าข้อมูลถูกเรียงลำดับแล้วและ O (n lg n) กรณีที่เลวร้ายที่สุด มันสวยงามมาก แต่ในทางปฏิบัติมันไม่ดีเท่าบางประเภทปรับตัวอื่น ๆ เช่น Timsort หรือ smoothsort
หากองค์ประกอบถูกจัดเรียงแล้วหรือมีเพียงไม่กี่องค์ประกอบก็จะเป็นกรณีการใช้งานที่สมบูรณ์แบบสำหรับ Insertion Sort!
การเรียงลำดับการแทรกต้องใช้เวลา O (n + จำนวนผู้รุกราน)
ผกผันคือคู่ดังกล่าวว่า(i, j)
i < j && a[i] > a[j]
นั่นคือคู่ที่ไม่เรียบร้อย
การวัดหนึ่งของการ "เรียงเกือบ" คือจำนวนของการรุกราน - หนึ่งสามารถใช้ "ข้อมูลที่เรียงเกือบ" เพื่อหมายถึงข้อมูลที่มีการรุกรานน้อย หากรู้ว่าจำนวนผู้รุกรานเป็นเส้นตรง (ตัวอย่างเช่นคุณเพิ่งผนวกองค์ประกอบ O (1) เข้ากับรายการที่เรียงลำดับ) การเรียงลำดับการแทรกใช้เวลา O (n)
อย่างที่คนอื่น ๆ พูดให้ระวังเรื่อง Quicksort ที่ไร้เดียงสา - ที่สามารถมีประสิทธิภาพ O (N ^ 2) ในการเรียงลำดับหรือเกือบเรียงลำดับข้อมูล อย่างไรก็ตามด้วยอัลกอริธึมที่เหมาะสมสำหรับการเลือกเดือย (ทั้งแบบสุ่มหรือค่ามัธยฐานของสาม - ดูการเลือกเดือยสำหรับ Quicksort ) Quicksort จะยังคงทำงานได้ตามปกติ
โดยทั่วไปแล้วความยากลำบากในการเลือกอัลกอริทึมเช่นการเรียงลำดับการแทรกนั้นเป็นการตัดสินใจเมื่อข้อมูลไม่เพียงพอที่ Quicksort จะเร็วขึ้น
ฉันจะไม่แกล้งมีคำตอบทั้งหมดที่นี่เพราะฉันคิดว่าการได้คำตอบจริงอาจต้องใช้อัลกอริธึมและการทำโปรไฟล์กับตัวอย่างข้อมูลตัวแทน แต่ฉันได้คิดถึงคำถามนี้ทุกเย็นและนี่คือสิ่งที่เกิดขึ้นกับฉันและบางคนเดาว่าอะไรดีที่สุด
ให้ N เป็นจำนวนรายการทั้งหมด, M คือจำนวนที่ไม่อยู่ในลำดับ
การเรียงลำดับฟองจะต้องทำบางอย่างเช่น 2 * M + 1 ผ่านรายการ N ทั้งหมด ถ้า M มีขนาดเล็กมาก (0, 1, 2?) ฉันคิดว่ามันจะยากมากที่จะเอาชนะ
หาก M มีขนาดเล็ก (พูดน้อยกว่า log N) การเรียงลำดับการแทรกจะมีประสิทธิภาพโดยเฉลี่ยที่ดี อย่างไรก็ตามหากมีเคล็ดลับที่ฉันไม่ได้เห็นมันจะมีประสิทธิภาพของเคสที่แย่ที่สุด (ใช่ไหมถ้ารายการสุดท้ายในคำสั่งมาก่อนคุณต้องแทรกทุกรายการเท่าที่ฉันเห็นซึ่งจะฆ่าประสิทธิภาพ) ฉันเดาว่ามีอัลกอริทึมการเรียงลำดับที่เชื่อถือได้มากขึ้นสำหรับสิ่งนี้ กรณี แต่ฉันไม่รู้ว่ามันคืออะไร
ถ้า M ใหญ่กว่า (พูดเท่ากันหรือดีกว่า log N) การเรียงครุ่นคิดนั้นดีที่สุดแน่นอน
ข้อยกเว้นทั้งหมด: ถ้าคุณรู้ล่วงหน้าว่าองค์ประกอบใดไม่ได้เรียงลำดับแล้วทางออกที่ดีที่สุดของคุณคือการดึงไอเท็มเหล่านั้นออกเรียงลำดับโดยใช้การเรียงลำดับแบบใคร่ครวญและผสานรายการที่เรียงสองรายการเข้าด้วยกัน หากคุณสามารถคิดได้อย่างรวดเร็วว่ารายการใดที่ไม่เป็นระเบียบนี่จะเป็นคำตอบทั่วไปที่ดีเช่นกัน - แต่ฉันไม่สามารถหาวิธีง่ายๆในการทำสิ่งนี้ได้
ความคิดเพิ่มเติม (ข้ามคืน): ถ้า M + 1 <N / M คุณสามารถสแกนรายการที่กำลังมองหา N / M ในแถวที่เรียงลำดับแล้วขยายการวิ่งในทิศทางใดทิศทางหนึ่งเพื่อหาสิ่งที่ไม่ต้องการ สั่งซื้อสินค้า ที่จะใช้การเปรียบเทียบ 2N มากที่สุด จากนั้นคุณสามารถเรียงลำดับรายการที่ไม่เรียงลำดับและทำการผสานที่เรียงลำดับในสองรายการ การเปรียบเทียบโดยรวมควรน้อยกว่าบางอย่างเช่น 4N + M log2 (M) ซึ่งจะเอาชนะชุดคำสั่งการเรียงลำดับแบบไม่เฉพาะเจาะจงใด ๆ ฉันคิดว่า (ยิ่งคิดยิ่งกว่านี้: มันยากกว่าที่ฉันคิด แต่ฉันก็ยังคิดว่ามันเป็นไปได้พอสมควร)
อีกการตีความของคำถามคืออาจมีหลายรายการที่ไม่เป็นไปตามคำสั่ง แต่พวกเขาอยู่ใกล้กับที่พวกเขาควรจะอยู่ในรายการ (ลองนึกภาพเริ่มต้นด้วยรายการที่เรียงลำดับและสลับรายการอื่น ๆ ด้วยรายการที่มาหลังจากนั้น) ในกรณีนี้ฉันคิดว่าการเรียงลำดับฟองมีประสิทธิภาพดีมาก - ฉันคิดว่าจำนวนรอบที่ผ่านจะเป็นสัดส่วนกับรายการที่ไกลที่สุด คือ. การเรียงลำดับการแทรกจะทำงานได้ไม่ดีนักเนื่องจากรายการสั่งซื้อทุกรายการจะทริกเกอร์การแทรก ฉันคิดว่าการเรียงลำดับครุ่นคิดหรือสิ่งที่จะทำงานได้ดีเช่นกัน
หากคุณต้องการใช้งานเฉพาะสำหรับการเรียงลำดับอัลกอริธึมโครงสร้างข้อมูลหรือสิ่งใดก็ตามที่มีลิงค์ไปด้านบนฉันขอแนะนำโครงการ"โครงสร้างโครงสร้างและอัลกอริทึม"ที่ยอดเยี่ยมบน CodePlex ได้หรือไม่?
มันจะมีทุกสิ่งที่คุณต้องการโดยไม่ต้องคิดค้นล้อใหม่
แค่เกลือเม็ดเล็ก ๆ ของฉัน
คอลเลกชันที่ดีของอัลกอริทึมการเรียงลำดับเพื่อจุดประสงค์นี้ในคำตอบดูเหมือนจะขาดGnome Sortซึ่งก็เหมาะสมและอาจต้องใช้ความพยายามในการปรับใช้ให้น้อยที่สุด
การเรียงลำดับการแทรกเป็นกรณีที่ดีที่สุด O (n) บนอินพุตที่เรียงลำดับ และอยู่ใกล้กับอินพุตที่เรียงลำดับส่วนใหญ่ (ดีกว่าเรียงลำดับอย่างรวดเร็ว)
ไตร่ตรองลองใช้ Heap ฉันเชื่อว่ามันสอดคล้องกันมากที่สุดของ O (n lg n) ทุกประเภท
Bubble-sort (หรือปลอดภัยกว่านั้นการจัดเรียงฟองสองทิศทาง) น่าจะเหมาะสำหรับรายการที่เรียงลำดับส่วนใหญ่แม้ว่าฉันเดิมพันหวีเรียง tweaked (มีขนาดช่องว่างเริ่มต้นที่ต่ำกว่ามาก) จะเร็วขึ้นเล็กน้อยเมื่อรายการไม่ได้ ' เรียงค่อนข้างสมบูรณ์แบบ หวีเรียง degrades เรียงฟอง -
มันขึ้นอยู่กับกรณีการใช้งาน หากคุณรู้ว่าองค์ประกอบใดที่มีการเปลี่ยนแปลงการลบและการแทรกจะเป็นกรณีที่ดีที่สุดเท่าที่ฉันกังวล
Bubble Sort เป็นผู้ชนะแน่นอนคนต่อไปที่เรดาร์จะเรียงลำดับการแทรก
เก็บให้ห่างจาก QuickSort - ไม่มีประสิทธิภาพในการจัดเรียงข้อมูลล่วงหน้า การเรียงลำดับการแทรกจะจัดการข้อมูลที่เกือบจะเรียงลำดับได้ดีด้วยการย้ายค่าน้อยที่สุด