Constant Time และ Amortized Constant Time ถือว่ามีประสิทธิภาพเทียบเท่าหรือไม่?


16

ฉันต้องเขียน RandomQueue ที่อนุญาตให้ผนวกและลบแบบสุ่มใน Constant Time (O (1))

ความคิดแรกของฉันคือการสำรองข้อมูลด้วย Array บางประเภท (ฉันเลือก ArrayList) เนื่องจากอาร์เรย์มีการเข้าถึงอย่างต่อเนื่องผ่านดัชนี

เมื่อมองไปที่เอกสารแม้ว่าฉันรู้ว่าการเพิ่มเติมของ ArrayLists ถือเป็น Amortized Constant Time เนื่องจากการเพิ่มอาจต้องมีการจัดสรรใหม่ของอาเรย์พื้นฐานซึ่งก็คือ O (n)

Amortized Constant Time และ Constant Time มีประสิทธิภาพเหมือนกันหรือไม่หรือฉันต้องดูโครงสร้างบางอย่างที่ไม่ต้องการการจัดสรรใหม่อย่างสมบูรณ์ในทุก ๆ การเติม

ฉันถามสิ่งนี้เพราะโครงสร้างแบบอาเรย์กัน (ซึ่งเท่าที่ฉันรู้จะมีการเพิ่มค่าคงที่ตลอดเวลา) ฉันไม่สามารถคิดอะไรที่ตรงตามข้อกำหนด:

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

นี่คือคำถามเต็ม ในกรณีที่ฉันเคลือบรายละเอียดที่สำคัญบางอย่าง:

ออกแบบและใช้งาน RandomQueue นี่เป็นการใช้งานอินเตอร์เฟสคิวที่การดำเนินการ remove () ลบองค์ประกอบที่ถูกสุ่มเลือกอย่างสม่ำเสมอระหว่างองค์ประกอบทั้งหมดที่อยู่ในคิว (คิดว่า RandomQueue เป็นกระเป๋าที่เราสามารถเพิ่มองค์ประกอบหรือเข้าถึงและลบองค์ประกอบสุ่มบางอย่างสุ่มสี่สุ่มห้า) การดำเนินการเพิ่ม (x) และ remove () ใน RandomQueue ควรทำงานในเวลาคงที่ต่อการดำเนินการ


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

มันไม่ได้ให้อะไรเฉพาะเจาะจง ความต้องการเป็นเพียงโครงสร้างที่ใช้อินเทอร์เฟซของคิวและมีการเพิ่มและลบ O (1)
Carcigenicate

ในฐานะที่เป็นกัน - อาร์เรย์ที่ปรับขนาดได้ที่มีการเติบโต O (n) ไม่จำเป็นต้องมีการเพิ่ม O (1): สิ่งนี้ขึ้นอยู่กับวิธีที่เราเติบโตอาร์เรย์ การเติบโตโดยจำนวนคงที่aยังคงเป็น O (n) สำหรับการเพิ่ม (เรามี1/aโอกาสสำหรับการดำเนินการ O (n)) แต่การเติบโตโดยปัจจัยคงที่a > 1คือ O (1) ตัดจำหน่ายสำหรับการเพิ่ม: เรามี(1/a)^nโอกาสของ O (n) การดำเนินงาน nแต่น่าจะเป็นที่ใกล้ศูนย์ขนาดใหญ่
amon

ArrayLists ใช้ตัวแก้ไขที่ถูกต้องหรือไม่
Carcigenicate

1
ผู้เขียนคำถาม (ฉัน) กำลังคิดถึงวิธีแก้ไขเวลาคงที่ที่ตัดจำหน่าย ฉันจะชี้แจงว่าในรุ่นถัดไป (ถึงแม้จะเป็นกรณีที่แย่ที่สุดก็สามารถทำได้โดยใช้เทคนิคการตัดจำหน่าย )
Pat Morin

คำตอบ:


10

Amortized Constant Time นั้นสามารถเทียบได้กับ Constant Time เกือบตลอดเวลาโดยที่ไม่ทราบถึงข้อมูลเฉพาะของแอปพลิเคชันของคุณและประเภทการใช้งานที่คุณวางแผนจะทำกับคิวนี้โอกาสส่วนใหญ่ที่คุณจะได้รับคือ

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

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


1
ประณามจุดที่ดีในการลบ; ฉันไม่ได้พิจารณาเรื่องนั้น และเนื่องจากเราสุ่มเอาองค์ประกอบออกไปนั่นไม่ได้หมายความว่าในทางเทคนิคแล้วมันจะไม่มีคิวในแง่นั้นอีกต่อไป?
Carcigenicate

ใช่มันหมายความว่าคุณไม่ได้ถือว่าเป็นคิวจริงๆ แต่ฉันไม่ทราบว่าคุณวางแผนที่จะค้นหารายการที่จะลบ หากกลไกการค้นหาพวกเขาคาดว่าพวกเขาจะอยู่ในคิวตามลำดับที่ถูกเพิ่มเข้ามาคุณก็จะโชคไม่ดี หากคุณไม่สนใจว่าคำสั่งซื้อของรายการได้รับการอ่านไม่ออกแสดงว่าคุณไม่เป็นไร
Mike Nakis

2
ความคาดหวังสำหรับฉันที่RandomQueueจะใช้Queueอินเทอร์เฟซและสำหรับremoveวิธีการที่ให้มาเพื่อลบแบบสุ่มแทนที่จะโผล่หัวดังนั้นจึงไม่มีวิธีใดที่จะพึ่งพาการสั่งซื้อที่เฉพาะเจาะจง ฉันคิดว่าเมื่อพิจารณาถึงลักษณะแบบสุ่มของมันแล้วผู้ใช้ไม่ควรคาดหวังให้มันรักษาลำดับเฉพาะ ฉันเสนอการบ้านในคำถามเพื่อขอความกระจ่าง ขอขอบคุณ.
Carcigenicate

2
ใช่แล้วดูเหมือนว่าคุณจะสบายดีถ้าคุณเพียงแค่ให้แน่ใจว่าการลบรายการเสร็จตามที่ฉันแนะนำ
Mike Nakis

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

14

คำถามที่ดูเหมือนว่าจะเฉพาะขอเวลาคงที่และไม่ได้เป็นเวลาคงตัดจำหน่าย ดังนั้นด้วยความเคารพต่อคำถามที่ยกมาไม่มีพวกเขาไม่ได้มีประสิทธิภาพเท่ากัน * อย่างไรก็ตามมีในแอปพลิเคชันในโลกแห่งความจริงหรือไม่?

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

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

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

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

* มีปัญหาเล็กน้อยที่นี่ เพื่อที่จะทำให้ภาชนะที่ใช้งานทั่วไปใด ๆ เป็นเวลาคงที่สำหรับการแทรกหนึ่งในสองสิ่งที่ต้องเก็บ:

  • ภาชนะจะต้องมีขนาดสูงสุดคงที่ หรือ
  • คุณสามารถสมมติว่าการจัดสรรหน่วยความจำของแต่ละองค์ประกอบเป็นเวลาคงที่

"เซิร์ฟเวอร์ตับ" ดูเหมือนจะเป็นคำพูดแปลก ๆ ที่จะใช้ที่นี่ คุณหมายถึง "live server" หรือเปล่า
Pieter Geerkens

6

ขึ้นอยู่กับว่าคุณกำลังปรับให้เหมาะสมสำหรับปริมาณงานหรือความล่าช้า:

  • ระบบที่ไวต่อความหน่วงแฝงต้องการประสิทธิภาพที่สม่ำเสมอ สำหรับสถานการณ์ดังกล่าวเราต้องเน้นพฤติกรรมที่เลวร้ายที่สุดของระบบ ตัวอย่างคือระบบแบบเรียลไทม์ที่อ่อนนุ่มเช่นเกมที่ต้องการบรรลุอัตราเฟรมที่สอดคล้องกันหรือเว็บเซิร์ฟเวอร์ที่ต้องส่งการตอบสนองภายในกรอบเวลาที่ จำกัด : การสูญเสียรอบ CPU จะดีกว่าการมาสาย
  • ระบบที่ได้รับการปรับปรุงประสิทธิภาพสูงสุดนั้นไม่สนใจแผงควบคุมเป็นครั้งคราวตราบใดที่ปริมาณข้อมูลสูงสุดสามารถประมวลผลได้ในระยะยาว ที่นี่เรามีความสนใจในผลการดำเนินงานตัดจำหน่ายเป็นหลัก โดยทั่วไปจะเป็นกรณีของการทำตัวเลขซ้ำซ้อนหรืองานประมวลผลแบทช์อื่น ๆ

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

นอกจากนี้ความซับซ้อนของอัลกอริทึมมักจะไม่สำคัญเท่าที่เราคิด: เมื่อปัญหาถูก จำกัด อยู่ที่จำนวนหนึ่งดังนั้นลักษณะที่แท้จริงและประสิทธิภาพของการวัดนั้นสำคัญกว่าพฤติกรรม“ สำหรับn ที่มีขนาดใหญ่มาก”


น่าเสียดายที่ฉันมีพื้นหลังน้อยมาก คำถามลงท้ายด้วย: "การดำเนินการเพิ่ม (x) และ remove () ใน RandomQueue ควรทำงานในเวลาคงที่ต่อการดำเนินการ"
Carcigenicate

2
@Carcigenicate เว้นแต่คุณจะทราบว่าระบบมีความไวต่อความหน่วงแฝงโดยใช้ความซับซ้อนที่ตัดจำหน่ายเพื่อเลือกโครงสร้างข้อมูลควรเพียงพออย่างยิ่ง
amon

ฉันมีความประทับใจนี่อาจเป็นแบบฝึกหัดการเขียนโปรแกรมหรือการทดสอบ และไม่ใช่เรื่องง่ายอย่างแน่นอน จริงอย่างแน่นอนว่ามันไม่ค่อยสำคัญ
gnasher729

1

หากคุณถูกขอให้ใช้อัลกอริทึม "เวลาคงที่ตัดจำหน่าย" บางครั้งอัลกอริทึมของคุณอาจใช้เวลานาน ตัวอย่างเช่นถ้าคุณใช้ std :: vector ใน C ++ เวกเตอร์ดังกล่าวอาจมีการจัดสรรพื้นที่สำหรับ 10 วัตถุและเมื่อคุณจัดสรรวัตถุที่ 11 จะมีการจัดสรรพื้นที่สำหรับ 20 วัตถุวัตถุ 10 รายการจะถูกคัดลอกและเพิ่มที่ 11 ซึ่ง ใช้เวลาพอสมควร แต่ถ้าคุณเพิ่มวัตถุหนึ่งล้านชิ้นคุณอาจมีการทำงานที่รวดเร็ว 999,980 รายการและการดำเนินงานช้า 20 ครั้งโดยมีเวลาเฉลี่ยที่รวดเร็ว

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

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