"Constant Amortized Time" หมายถึงอะไรเมื่อพูดถึงความซับซ้อนของเวลาของอัลกอริทึม?
"Constant Amortized Time" หมายถึงอะไรเมื่อพูดถึงความซับซ้อนของเวลาของอัลกอริทึม?
คำตอบ:
เวลาค่าตัดจำหน่ายอธิบายในแง่ง่าย:
หากคุณทำการผ่าตัดหนึ่งล้านครั้งคุณจะไม่สนใจกรณีที่เลวร้ายที่สุดหรือกรณีที่ดีที่สุดของการดำเนินการนั้น - สิ่งที่คุณใส่ใจคือเวลาทั้งหมดที่ใช้ไปเมื่อคุณทำซ้ำเป็นล้านครั้ง .
ดังนั้นจึงไม่สำคัญว่าการดำเนินการจะช้ามากสักครู่ตราบใดที่ "นาน ๆ ครั้ง" นั้นหายากพอที่ความช้าจะถูกทำให้เจือจาง เวลาที่ตัดจำหน่ายอย่างมีนัยสำคัญหมายถึง "เวลาเฉลี่ยที่ใช้ต่อการดำเนินการหากคุณดำเนินการหลายอย่าง" เวลาตัดจำหน่ายไม่จำเป็นต้องคงที่ คุณสามารถมีเวลาตัดจำหน่ายเชิงเส้นและลอการิทึมหรืออะไรก็ได้
ลองมาดูตัวอย่างของอาร์เรย์แบบไดนามิกที่คุณเพิ่มไอเท็มใหม่ซ้ำ ๆ โดยปกติการเพิ่มรายการต้องใช้เวลาคงที่ (นั่นคือO(1)
) แต่ทุกครั้งที่อาร์เรย์เต็มคุณจัดสรรพื้นที่ให้มากขึ้นเป็นสองเท่าคัดลอกข้อมูลของคุณไปยังภูมิภาคใหม่และเพิ่มพื้นที่ว่างเก่า สมมติว่าการจัดสรรและเพิ่มการรันในเวลาคงที่กระบวนการขยายนี้ใช้O(n)
เวลาโดยที่ n คือขนาดปัจจุบันของอาร์เรย์
ดังนั้นทุกครั้งที่คุณขยายคุณจะใช้เวลาประมาณสองเท่าของการขยายครั้งสุดท้าย แต่คุณก็ต้องรอนานกว่าสองเท่าก่อนจะทำ! ค่าใช้จ่ายของการขยายแต่ละครั้งจึงสามารถ "กระจาย" ในการแทรก ซึ่งหมายความว่าในระยะยาวรวมเวลาดำเนินการสำหรับการเพิ่มมรายการที่จะอาร์เรย์O(m)
และเพื่อให้เวลาตัดจำหน่าย (เช่นครั้งต่อแทรก) O(1)
เป็น
นั่นหมายความว่าเมื่อเวลาผ่านไปสถานการณ์กรณีที่เลวร้ายที่สุดจะเริ่มต้นที่ O (1) หรือเวลาคงที่ ตัวอย่างทั่วไปคืออาร์เรย์แบบไดนามิก หากเราได้จัดสรรหน่วยความจำสำหรับรายการใหม่แล้วการเพิ่มจะเป็น O (1) หากเราไม่ได้จัดสรรมันเราจะทำโดยการจัดสรรพูดสองเท่าของจำนวนเงินปัจจุบัน การแทรกแบบพิเศษนี้จะไม่เป็น O (1) แต่เป็นอย่างอื่น
สิ่งสำคัญคืออัลกอริทึมรับประกันว่าหลังจากดำเนินการตามลำดับการดำเนินงานที่มีราคาแพงจะถูกตัดจำหน่ายและทำให้การดำเนินการทั้งหมด O (1)
หรือในเงื่อนไขที่เข้มงวดมากขึ้น
มีค่าคงที่ c เช่นว่าสำหรับ ทุกลำดับของการดำเนินการ (เช่นเดียวกับที่ลงท้ายด้วยการดำเนินการที่มีราคาแพง) ความยาว L เวลาไม่เกิน c * L (ขอบคุณRafał Dowgird )
ในการพัฒนาวิธีคิดที่เป็นธรรมชาติให้ลองพิจารณาการแทรกองค์ประกอบในอาร์เรย์แบบไดนามิก (ตัวอย่างเช่นstd::vector
ใน C ++) ลองพล็อตกราฟที่แสดงการพึ่งพาจำนวนของการดำเนินการ (Y) ที่จำเป็นในการแทรกองค์ประกอบ N ในอาร์เรย์:
ส่วนแนวตั้งของกราฟสีดำสอดคล้องกับการจัดสรรหน่วยความจำใหม่เพื่อขยายอาร์เรย์ ที่นี่เราจะเห็นได้ว่าการขึ้นต่อกันนี้สามารถแสดงเป็นเส้นตรงได้ และสมการเส้นนี้คือY=C*N + b
( C
คงที่b
= 0 ในกรณีของเรา) ดังนั้นเราจึงสามารถพูดได้ว่าเราจำเป็นต้องใช้C*N
การดำเนินงานโดยเฉลี่ยเพื่อเพิ่มองค์ประกอบ N ไปยังอาร์เรย์หรือC*1
การดำเนินงานเพื่อเพิ่มองค์ประกอบหนึ่ง (เวลาคงที่ตัดจำหน่าย)
ฉันพบคำอธิบาย Wikipedia ด้านล่างนี้มีประโยชน์หลังจากอ่านซ้ำ 3 ครั้ง:
ที่มา: https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array
"อาร์เรย์แบบไดนามิก
การวิเคราะห์ค่าตัดการดำเนินการกดสำหรับอาร์เรย์แบบไดนามิก
พิจารณาอาร์เรย์แบบไดนามิกที่มีขนาดใหญ่ขึ้นเมื่อมีการเพิ่มองค์ประกอบอื่น ๆ เข้าไปเช่น ArrayList ใน Java หากเราเริ่มต้นด้วยอาร์เรย์ที่มีขนาดไดนามิก 4 มันต้องใช้เวลาคงที่ในการผลักดันองค์ประกอบทั้งสี่ลงไป แต่การผลักองค์ประกอบที่ห้าไปยังอาร์เรย์นั้นจะใช้เวลานานขึ้นเนื่องจากอาร์เรย์จะต้องสร้างอาร์เรย์ใหม่ที่มีขนาดปัจจุบันเป็นสองเท่า (8) คัดลอกองค์ประกอบเก่าไปยังอาร์เรย์ใหม่แล้วเพิ่มองค์ประกอบใหม่ การดำเนินการพุชสามครั้งถัดไปจะใช้เวลาคงที่ในทำนองเดียวกันและจากนั้นการเพิ่มที่ตามมาจะต้องเพิ่มขนาดอาเรย์เป็นสองเท่าช้าๆ
โดยทั่วไปหากเราพิจารณาจำนวนการกด n โดยไม่เจาะจงกับอาร์เรย์ที่มีขนาด n เราสังเกตว่าการดำเนินการกดใช้เวลาคงที่ยกเว้นครั้งสุดท้ายที่ใช้เวลา O (n) ในการดำเนินการเพิ่มขนาดเป็นสองเท่า เนื่องจากมีการดำเนินงานทั้งหมด n รายการเราจึงสามารถหาค่าเฉลี่ยของสิ่งนี้และพบว่าสำหรับการผลักองค์ประกอบเข้าสู่อาร์เรย์แบบไดนามิกนั้นต้องใช้: O (n / n) = O (1), เวลาคงที่ "
เพื่อความเข้าใจของฉันเป็นเรื่องง่าย:
สมมติว่าคุณมีเงินจำนวนมาก และคุณต้องการที่จะรวมไว้ในห้อง และคุณมีมือและขายาวตราบใดที่คุณต้องการในตอนนี้หรือในอนาคต และคุณต้องกรอกข้อมูลทั้งหมดในห้องเดียวดังนั้นมันง่ายที่จะล็อค
ดังนั้นคุณไปทางขวา / สิ้นสุดของห้องและเริ่มซ้อนกัน ในขณะที่คุณสแต็คห้องช้าๆจะไม่มีพื้นที่เหลือ อย่างไรก็ตามในขณะที่คุณเติมมันเป็นเรื่องง่ายที่จะกองพวกเขา เตรียมพร้อมรับเงินใส่เงิน ง่าย. มันคือ O (1) เราไม่จำเป็นต้องย้ายเงินก่อนหน้านี้
เมื่อห้องหมดพื้นที่ เราต้องการห้องอื่นซึ่งใหญ่กว่า ที่นี่มีปัญหาเนื่องจากเราสามารถมีเพียง 1 ห้องเพื่อให้เราสามารถล็อคได้เพียง 1 เราจึงต้องย้ายเงินที่มีอยู่ทั้งหมดในห้องนั้นไปยังห้องใหม่ที่ใหญ่กว่า ดังนั้นย้ายเงินทั้งหมดจากห้องเล็กไปยังห้องที่ใหญ่กว่า นั่นคือกองทั้งหมดทั้งหมดอีกครั้ง ดังนั้นเราจำเป็นต้องย้ายเงินก่อนหน้านี้ทั้งหมด ดังนั้นมันคือ O (N) (สมมติว่า N คือจำนวนเงินทั้งหมดของเงินก่อนหน้า)
กล่าวอีกนัยหนึ่งมันง่ายจนถึง N เพียงปฏิบัติการเดียว แต่เมื่อเราต้องการย้ายไปยังห้องที่ใหญ่กว่า ถ้าเราเฉลี่ยมันก็คือ 1 ส่วนแทรกในการเริ่มต้นและอีก 1 ย้ายในขณะที่ย้ายไปที่ห้องอื่น รวมการดำเนินการ 2 การแทรกครั้งเดียวหนึ่งย้าย
สมมติว่า N มีขนาดใหญ่เช่น 1 ล้านแม้ในห้องเล็กการดำเนินการ 2 เมื่อเทียบกับ N (1 ล้าน) ไม่ได้เป็นจำนวนที่เปรียบเทียบได้ดังนั้นจึงถือว่าเป็นค่าคงที่หรือ O (1)
สมมติว่าเมื่อเราทำทั้งหมดข้างต้นในอีกห้องที่ใหญ่กว่าและต้องย้ายอีกครั้ง มันยังคงเหมือนเดิม พูด N2 (พูด 1 พันล้าน) เป็นจำนวนเงินใหม่ในห้องที่ใหญ่กว่า
ดังนั้นเรามี N2 (ซึ่งรวมถึง N จากก่อนหน้านี้เนื่องจากเราย้ายจากห้องเล็กไปใหญ่)
เรายังคงต้องการการดำเนินการเพียง 2 ครั้งโดยที่หนึ่งจะถูกแทรกเข้าไปในห้องที่ใหญ่กว่าและอีกการดำเนินการย้ายเพื่อย้ายไปยังห้องที่ใหญ่กว่า
ดังนั้นแม้สำหรับ N2 (1 พันล้าน) ก็เป็น 2 การดำเนินการสำหรับแต่ละ ซึ่งไม่มีอะไรอีกแล้ว ดังนั้นมันจึงเป็นค่าคงที่หรือ O (1)
ดังนั้นเมื่อ N เพิ่มขึ้นจาก N เป็น N2 หรืออื่น ๆ มันไม่สำคัญเท่าไหร่ มันยังคงที่หรือการดำเนินการ O (1) ที่จำเป็นสำหรับแต่ละ N
ทีนี้สมมติว่าคุณมี N เป็น 1 เล็กมากนับเงินน้อยและคุณมีห้องเล็กมากซึ่งจะพอดีกับเงินนับ 1
ทันทีที่คุณเติมเงินในห้องห้องนั้นก็จะเต็ม
เมื่อคุณไปที่ห้องที่ใหญ่กว่าให้คิดว่ามันสามารถเก็บเงินได้มากขึ้นเพียงหนึ่งเดียวรวมเป็นเงิน 2 จำนวน นั่นหมายความว่าเงินก่อนหน้านี้ถูกย้ายและอีก 1 และอีกครั้งมันเต็มไป
ด้วยวิธีนี้ N เติบโตอย่างช้าๆและไม่มีค่าคงตัว O (1) เนื่องจากเราย้ายเงินทั้งหมดจากห้องก่อนหน้า แต่สามารถเติมเงินได้เพียง 1 เท่านั้น
หลังจาก 100 ครั้งห้องใหม่จะพอดีกับเงินนับ 100 จากก่อนหน้านี้และอีก 1 เงินที่สามารถรองรับได้ นี่คือ O (N) เนื่องจาก O (N + 1) คือ O (N) นั่นคือระดับ 100 หรือ 101 เหมือนกันทั้งสองเป็นร้อยเมื่อเทียบกับเรื่องราวก่อนหน้าของคนหลายล้านและหลายพันล้านคน .
ดังนั้นนี่เป็นวิธีที่ไม่มีประสิทธิภาพในการจัดสรรห้อง (หรือหน่วยความจำ / RAM) สำหรับเงินของเรา (ตัวแปร)
วิธีที่ดีคือการจัดสรรพื้นที่ให้มากขึ้นด้วยกำลัง 2
ขนาดห้องพัก 1 = พอดี 1 นับเงิน
ขนาดห้องพักที่ 2 = พอดี 4 นับเงิน
ขนาด 3 ห้อง = พอดี 8 นับเงิน
ขนาดห้องพักที่ 4 = พอดี 16 นับเงิน
ขนาดห้องพัก 5 = พอดี 32 นับเงิน
ขนาดห้องพัก 6 = พอดี 64 นับเงิน
ขนาดห้องพัก 7 = พอดี 128 นับเงิน
ขนาดห้องพัก 8 = พอดี 256 นับเงิน
ขนาดห้องพัก 9 = 512 เหมาะกับการนับเงิน
ขนาดห้องพัก 10 = 1024 เหมาะกับการนับเงิน
ขนาดห้องพัก 11 = 2,048
เหมาะกับการนับเงิน..
ขนาดห้องที่ 16 = พอดีกับ 65,536 นับเงิน
...
ขนาดห้องที่ 32 = เหมาะกับ 4,294,967,296 จำนวนเงิน
...
ขนาดห้องที่ 64 = เหมาะกับ 18,446,744,073,709,551,616 เงิน
ทำไมสิ่งนี้ถึงดีกว่า เพราะมันดูเหมือนจะเติบโตอย่างช้าๆในช่วงเริ่มต้นและเร็วกว่านั่นคือเมื่อเทียบกับปริมาณหน่วยความจำใน RAM ของเรา
สิ่งนี้มีประโยชน์เพราะในกรณีแรกแม้ว่ามันจะดีงานที่ต้องทำทั้งหมดต่อเงินได้รับการแก้ไข (2) และไม่เทียบเท่ากับขนาดห้อง (N) ห้องที่เราถ่ายในระยะแรกอาจจะเกินไป ใหญ่ (1 ล้าน) ที่เราอาจไม่ได้ใช้อย่างเต็มที่ขึ้นอยู่กับว่าเราจะได้รับเงินจำนวนมากเพื่อประหยัดเลยในกรณีแรก
อย่างไรก็ตามในกรณีสุดท้ายพลังของ 2 มันเติบโตในขอบเขตของ RAM ของเรา ดังนั้นการเพิ่มพลังของ 2 ทั้งการวิเคราะห์ Armotized จึงยังคงที่และเป็นมิตรกับ RAM ที่ จำกัด ที่เรามีอยู่ในปัจจุบัน
คำอธิบายข้างต้นนำไปใช้กับการวิเคราะห์โดยรวมความคิดในการ "เฉลี่ย" เหนือการดำเนินการหลายอย่าง ฉันไม่แน่ใจว่าวิธีการเหล่านี้ใช้กับวิธีการของธนาคารหรือวิธีการทางฟิสิกส์ของการวิเคราะห์ค่าตัดจำหน่าย
ตอนนี้ ฉันไม่แน่ใจในคำตอบที่ถูกต้อง แต่มันจะต้องเกี่ยวข้องกับเงื่อนไขของหลักการของนักฟิสิกส์ + วิธีการของแบงเกอร์:
(ผลรวมของต้นทุนการดำเนินงานที่ตัดจำหน่าย)> = (ผลรวมของต้นทุนการดำเนินงานจริง)
ปัญหาหลักที่ฉันเผชิญคือเนื่องจากค่าใช้จ่ายในการดำเนินการค่าแอมโมติคแตกต่างจากค่าใช้จ่ายแบบปกติฉันไม่แน่ใจว่าจะให้คะแนนนัยสำคัญของต้นทุนที่ตัดจำหน่าย
นั่นคือเมื่อมีคนให้ต้นทุนตัดจำหน่ายของฉันฉันรู้ว่ามันไม่เหมือนกับค่าใช้จ่ายแบบปกติที่ฉันจะได้ข้อสรุปอะไรจากค่าตัดจำหน่ายต้นทุนแล้ว
เนื่องจากเรามีกรณีของการปฏิบัติการบางอย่างที่ถูกคิดค่าใช้จ่ายมากเกินไปในขณะที่การดำเนินงานอื่น ๆ มีการคิดค่าใช้จ่ายต่ำสมมติฐานหนึ่งอาจเป็นไปได้ว่าการเสนอราคาตัดจำหน่าย - ค่าใช้จ่ายของการดำเนินงานแต่ละรายการจะไม่มีความหมาย
ตัวอย่างเช่น: สำหรับฟีโบนักชีฮีปการอ้างถึงค่าตัดจำหน่ายของ Just Decreasing-Key เป็น O (1) นั้นไม่มีความหมายเนื่องจากค่าใช้จ่ายจะลดลงด้วย "งานที่ดำเนินการก่อนหน้านี้เพื่อเพิ่มศักยภาพของฮีป"
หรือ
เราอาจมีสมมติฐานอีกข้อหนึ่งที่ทำให้เกิดค่าใช้จ่ายตัดจำหน่ายดังนี้
ฉันรู้ว่าการดำเนินการที่มีราคาแพงจะถูกนำหน้าด้วยการดำเนินการต้นทุนต่ำหลายรายการ
เพื่อการวิเคราะห์ฉันจะคิดค่าใช้จ่ายในการดำเนินการที่มีต้นทุนต่ำเกินไปซึ่งหมายความว่าค่าใช้จ่ายที่ไม่ได้เปลี่ยนแปลงของพวกเขา
ด้วยการดำเนินการต้นทุนต่ำที่เพิ่มขึ้นเหล่านี้ฉันสามารถพิสูจน์ได้ว่าการดำเนินการที่มีราคาแพงมีค่าใช้จ่ายที่น้อยกว่า
ดังนั้นฉันจึงปรับปรุง / ลด ASYMPTOTIC-BOUND ของต้นทุนการดำเนินงาน n
ดังนั้นการวิเคราะห์ต้นทุนตัดจำหน่าย + ค่าตัดจำหน่ายต้นทุนขอบเขตตอนนี้ใช้กับการดำเนินงานที่มีราคาแพงเท่านั้น การดำเนินการราคาถูกมีค่าใช้จ่าย asymptotic ค่าตัดจำหน่ายเช่นเดียวกับค่า asymptotic ปกติของพวกเขา
ประสิทธิภาพของฟังก์ชั่นใด ๆ สามารถหาค่าเฉลี่ยได้โดยการหาร "จำนวนการเรียกใช้ฟังก์ชันทั้งหมด" เป็น "เวลารวมทั้งหมดสำหรับการโทรเหล่านั้นทั้งหมด" แม้แต่ฟังก์ชั่นที่ใช้เวลานานขึ้นและนานขึ้นสำหรับการโทรแต่ละครั้งคุณก็สามารถเฉลี่ยได้ด้วยวิธีนี้
ดังนั้นสาระสำคัญของฟังก์ชั่นที่ทำงานที่Constant Amortized Time
นี่คือ "เวลาเฉลี่ย" ถึงเพดานที่ไม่ได้รับเกินจำนวนการโทรยังคงเพิ่มขึ้น การโทรใด ๆ โดยเฉพาะอาจมีประสิทธิภาพแตกต่างกัน แต่ในระยะยาวเวลานี้โดยเฉลี่ยจะไม่เติบโตและยิ่งใหญ่ขึ้นเรื่อย ๆ
Constant Amortized Time
นี่คือบุญที่สำคัญของสิ่งที่ดำเนินการที่