การเพิ่มองค์ประกอบให้กับอาร์เรย์ที่เรียงลำดับ


31

อะไรจะเป็นวิธีที่เร็วที่สุดในการทำสิ่งนี้ (จากมุมมองอัลกอริทึมเช่นเดียวกับเรื่องจริง)

ฉันกำลังคิดอะไรบางอย่างตามบรรทัดต่อไปนี้

ฉันสามารถเพิ่มในตอนท้ายของอาร์เรย์แล้วใช้ bubbleort เนื่องจากมีกรณีที่ดีที่สุด (เรียงลำดับทั้งหมดตอนเริ่มต้น) ที่อยู่ใกล้กับนี้และมีเวลาทำงานเชิงเส้น (ในกรณีที่ดีที่สุด)

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

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

วิธีนี้ทำได้ดีที่สุด?


1
วิธีที่เร็วที่สุดถ้าคุณต้องทำบ่อยๆคืออย่าใช้อาร์เรย์ในตอนแรก
reinierpost

ปรับสมดุลต้นไม้ไบนารีคุณหมายถึงอะไร?
soandos

ใช่เป็นไปได้; ดูคำตอบ ...
reinierpost

คำตอบ:


25

เรานับจำนวนขององค์ประกอบอาร์เรย์อ่านและเขียน หากต้องการเรียงลำดับฟองอากาศคุณต้องมีการเข้าถึง (การเขียนเริ่มต้นไปยังจุดสิ้นสุดจากนั้นในกรณีที่เลวร้ายที่สุดสองครั้งอ่านและสองเขียนเพื่อทำnสลับ) ในการค้นหาไบนารีเราต้องการ2 log n + 2 n + 1 ( 2 log nสำหรับการค้นหาแบบไบนารีจากนั้นในกรณีที่เลวร้ายที่สุด2 nเพื่อเลื่อนองค์ประกอบอาร์เรย์ไปทางขวาแล้ว 1 เพื่อเขียนองค์ประกอบอาร์เรย์ไปที่ ตำแหน่งที่เหมาะสม)1+4nn2logn+2n+12logn2n

ดังนั้นทั้งสองวิธีจึงมีความซับซ้อนเหมือนกันสำหรับการใช้งานอาร์เรย์ แต่วิธีการค้นหาแบบไบนารีต้องการการเข้าถึงอาร์เรย์ที่น้อยลงในระยะยาว ... มีปัจจัยอื่น ๆ ที่เล่นตามธรรมชาติ

ที่จริงแล้วคุณสามารถใช้การใช้งานที่ดีขึ้นและนับเฉพาะการเข้าถึงอาร์เรย์จริง (ไม่เข้าถึงองค์ประกอบที่จะแทรก) คุณสามารถทำสำหรับฟองเรียงลำดับและเข้าสู่ระบบn + 2 n + 1สำหรับการค้นหาไบนารี ... ดังนั้นหากการเข้าถึงลงทะเบียน / แคชมีราคาถูกและการเข้าถึงอาร์เรย์ที่มีราคาแพงจากการค้นหาที่สิ้นสุดและขยับไปพร้อมกัน (อย่างชาญฉลาด การเรียงลำดับฟองสำหรับการแทรก) อาจทำได้ดีกว่าแม้ว่าจะไม่ใช่แบบไม่แสดงอาการ2n+1logn+2n+1

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

โปรดทราบด้วยว่าหากคุณต้องการเพิ่มองค์ประกอบลงในอาร์เรย์ที่เรียงลำดับขององค์ประกอบnความคิดที่ดีอาจเป็นการเรียงลำดับรายการmอย่างมีประสิทธิภาพจากนั้นจึงรวมสองอาร์เรย์เข้าด้วยกัน นอกจากนี้อาร์เรย์ที่เรียงลำดับสามารถสร้างได้อย่างมีประสิทธิภาพโดยใช้เช่นฮีป (เรียงลำดับฮีพ)mnม.


1
"ตารางแฮชอาจมีการแทรก & การลบ O (1)" - ตัดจำหน่ายแล้วโดยปกติ
ราฟาเอล

8
ตัดจำหน่ายคาดว่า
JeffE

BST มีสำหรับการค้นหาและแทรก (วิกิพีเดีย) ดังนั้นทำไมจึงไม่แนะนำให้เลือกที่นี่? O ( 2 l o g n )เพื่อค้นหาและแทรก O(ล.โอก. n)O(2 ล.โอก. n)
Kashyap


8

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

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

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

อย่างไรก็ตามฉันไม่เห็นเหตุผลใด ๆ ที่จะดึงฟองออกมาสำหรับปัญหานี้


2
O

+1 สำหรับการถูกกล่าวโทษ .. :-)
Kashyap

4

Patrick87 อธิบายทั้งหมดนี้เป็นอย่างดี แต่การปรับให้เหมาะสมอีกอย่างหนึ่งที่คุณสามารถทำได้ก็คือใช้สิ่งที่คล้ายกับบัฟเฟอร์แบบวงกลม: คุณสามารถย้ายรายการทางด้านขวาของตำแหน่งขององค์ประกอบที่แทรกไปทางขวาได้ตามปกติ แต่คุณสามารถย้ายรายการไปทางซ้ายของตำแหน่งที่ถูกต้องไปทางซ้าย ในการทำเช่นนี้คุณจะต้องถือว่าอาร์เรย์เป็นวงกลมนั่นคือรายการสุดท้ายอยู่ก่อนหน้าแรกและคุณต้องเก็บดัชนีที่รายการเริ่มต้นในปัจจุบัน

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


4

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


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