อัลกอริธึมที่กำหนดขึ้นเอง (โดยไม่มีตัวเปรียบเทียบ) ต่อไปนี้ใช้สำหรับ tuple อินพุต (a1,…,an):
- ทำการสับเปลี่ยน Fisher-Yatesโดยใช้เครื่องมือเปรียบเทียบกับคู่คงที่บางตัว (พูดa1<a2) เป็นการพลิกเหรียญ (ทำการสุ่มตัวอย่างปฏิเสธการยอมรับ) ถ้าตัวเปรียบเทียบเอาท์พุท1 ในครั้งแรกให้ใช้มันคว่ำเพื่อหลีกเลี่ยงการปฏิเสธการวนซ้ำในกรณีที่กำหนดขึ้น
- (เร่งความเร็วเพิ่มเติม: ลองคู่เดียว n ครั้งที่ไหน nคือความยาวหรืออินพุตของคุณ หากสองผลลัพธ์ใด ๆ กลับต่างกันจะได้การเปลี่ยนแปลงที่ได้ใน (1)
- จัดเรียงอาร์เรย์ของคุณโดยใช้การจัดเรียงผสาน
ให้ลำดับความสัมพันธ์ที่กำหนดไว้ล่วงหน้าเป็นตัวเปรียบเทียบอัลกอริทึมนี้จะเรียงลำดับอาร์เรย์ในเวลา O(nlogn) ตั้งแต่การสับเปลี่ยน Fisher-Yates ทำงาน O(n) ใช้สูงสุด O(logn)"บิตสุ่ม" ที่ไม่ใช่สุ่ม (เช่นการเรียกไปยังเครื่องมือเปรียบเทียบของคุณ) ในแต่ละขั้นตอนและการเรียงแบบผสานมีความซับซ้อนเชิงซีมโทติคเหมือนกัน ผลลัพธ์ของ (1) ไร้ประโยชน์โดยสิ้นเชิงในกรณีนี้ แต่เนื่องจากตามมาด้วยการเรียงลำดับจริงจึงไม่เป็นอันตราย
เมื่อมีการพลิกเหรียญจริงเมื่อเปรียบเทียบ (1) อนุญาตอาร์เรย์ที่มีความน่าจะเป็นเท่ากันสำหรับการเปลี่ยนแปลงแต่ละครั้งและถ้าคุณต้องทำจริง ๆ (3) (คุณออกไป (2) หรือ (2) ล้มเหลวในการพิจารณาแบบสุ่ม) นี่ไม่ใช่ เป็นอันตรายเนื่องจากการกระจายของผลลัพธ์ขึ้นอยู่กับลำดับของอินพุตที่กระจายอย่างสม่ำเสมอในทุกวิธีเรียงสับเปลี่ยนเนื่องจาก (1) ดังนั้นผลลัพธ์ของอัลกอริธึมทั้งหมดจึงกระจายอย่างสม่ำเสมอ จำนวนครั้งที่ต้องสุ่มตัวอย่างการปฏิเสธการตอบรับซ้ำแต่ละครั้งมีการกระจายเชิงเรขาคณิต (ปฏิเสธด้วยความน่าจะเป็น<12) และดังนั้นจึงมีค่าที่คาดหวัง <2. การทำซ้ำแต่ละครั้งจะใช้อย่างมากที่สุดlognบิตดังนั้นการวิเคราะห์รันไทม์เกือบเช่นเดียวกับในกรณีที่กำหนด แต่เราเท่านั้นที่จะได้รับการรันไทม์คาดของO(nlogn)ด้วยความเป็นไปได้ของการกำจัด (สิ้นสุดเพียงเกือบแน่นอน )
ดังที่โจชี้: ถ้าคุณไม่ชอบการทดสอบบิตแรกใน (1) ให้ทำ (3) จากนั้น (1) และใช้ an<a1 ซึ่งเป็นเสมอ 0เนื่องจากอาร์เรย์ถูกเรียงลำดับแล้วในกรณีที่กำหนดขึ้น นอกจากนี้คุณต้องลบจำนวนสุ่มของคุณจากขอบเขตบนของช่วงในลูปเนื่องจากขอบเขตบนของหมายเลขสุ่มจะทำให้เกิดการเปลี่ยนแปลงที่เหมือนกัน แต่โปรดระวังว่า (2) นั้นเป็นสิ่งต้องห้ามเพราะคุณจะต้องสับเปลี่ยนในกรณีเรียกค่าไถ่เสมอ
คุณสามารถใช้การโทรเดียวกันกับตัวเปรียบเทียบของคุณสำหรับ (1) และ (3) แต่จากนั้นพิสูจน์ว่าผลลัพธ์ที่ได้มีการกระจายอย่างสม่ำเสมอนั้นยากกว่ามากหากเป็นไปได้
อัลกอริทึมต่อไปนี้ไม่มีเฟสที่แตกต่างกันในการสุ่มและเรียงลำดับ แต่ช้าลงแบบไม่แสดงอาการ มันเป็นหลัก
จัดเรียงแทรกกับการค้นหาแบบไบนารี
ฉันจะใช้
a=(a1,…,an) เพื่อแสดงถึงอินพุตและ
bk=(bk,1,…,bk,k) เพื่อแสดงผลลัพธ์หลังจาก
k- รอบที่:
- ชุด b1,1=a1
- ถ้า a2<a1 แล้วก็ b2=(a2,a1) และ (c,d):=(2,1) อื่น b2=(a1,a2) และ (c,d):=(1,2). ไม่ว่าในกรณีใดad<ac จะเป็น 0 (เช่นเท็จ) สำหรับเครื่องมือเปรียบเทียบแบบไม่สุ่ม
- ที่จะได้รับ bk สำหรับ k≥3 ได้รับ bk−1 เป็นครั้งแรก
- ปล่อย l=⌈log2k⌉ และ k′=2lเช่น k′ เป็นพลังที่น้อยที่สุด 2 ไม่เล็กกว่า k.
- ปล่อย i0=0. สำหรับทุกคนj∈{1,…,l} ปล่อย
ij=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪ij−1+2l−jij−1ij−1+2l−jij−1ij−1+2l−j>k−1∧ad<acij−1+2l−j>k−1∧¬(ad<ac)ij−1+2l−j≤k−1∧bk−1,ij−1+2l−j<akij−1+2l−j≤k−1∧¬(bk−1,ij−1+2l−j<ak)
- ถ้า ผมล.> k ทำซ้ำ (5. ) อื่น ๆ ขk= (ขk - 1 , 1, … ,ขk - 1 ,ผมล.- 1,ak,ขk - 1 ,ผมล., … ,ขk - 1 , k - 1)
- เอาท์พุต ขn
กรณีสุ่ม: 5 + ถ้าข้อ 6 เป็นตัวอย่างการยอมรับ - ปฏิเสธเป็นหลัก อัลกอริทึมที่เหลือคือการสลับแบบไร้เดียงสา: สับเปลี่ยนเป็นอันดับแรกk - 1 องค์ประกอบและเพิ่ม kองค์ประกอบ -th ของแต่ละตำแหน่งที่มีความน่าจะเป็นที่เท่ากัน หากเราใช้การเรียงลำดับการแทรกแบบปกติเราจะได้การแจกแจงแบบทวินามแทน
โปรดทราบว่าอัลกอริทึมนี้ไม่มีประสิทธิภาพในทั้งสองโหมดเมื่อเปรียบเทียบกับการสับเปลี่ยนแบบ Fisher-Yates และการเรียงแบบผสานขณะที่การแทรกองค์ประกอบไปยังตำแหน่งที่กำหนดเองจะมีราคาแพงหากใช้อาร์เรย์และการค้นหาแบบไบนารี่ต้องการเวลาเชิงเส้น แต่บางทีการดัดแปลง heap sort หรือ tree sort ในทำนองเดียวกันอาจทำให้อัลกอริทึมเร็วขึ้น