โครงสร้างข้อมูลใดที่คุณสามารถใช้เพื่อให้คุณสามารถลบและแทนที่ O (1) หรือคุณจะหลีกเลี่ยงสถานการณ์เมื่อคุณต้องการโครงสร้างดังกล่าวได้อย่างไร
ST
monad ใน Haskell ทำอย่างนี้เนี่ย
โครงสร้างข้อมูลใดที่คุณสามารถใช้เพื่อให้คุณสามารถลบและแทนที่ O (1) หรือคุณจะหลีกเลี่ยงสถานการณ์เมื่อคุณต้องการโครงสร้างดังกล่าวได้อย่างไร
ST
monad ใน Haskell ทำอย่างนี้เนี่ย
คำตอบ:
มีโครงสร้างข้อมูลจำนวนมากที่ใช้ประโยชน์จากความเกียจคร้านและเทคนิคอื่น ๆ เพื่อให้ได้ค่าคงที่ที่ถูกตัดจำหน่ายหรือแม้กระทั่ง (สำหรับบางกรณีเช่นคิว ) การปรับปรุงเวลาคงที่สำหรับปัญหาหลายประเภท คริสโอคาสากิของวิทยานิพนธ์ปริญญาเอก "หน้าที่หมดจดโครงสร้างข้อมูล" และหนังสือชื่อเดียวกันเป็นตัวอย่างที่สำคัญ (อาจจะเป็นครั้งแรกที่หนึ่ง) แต่ข้อมูลได้สูงตั้งแต่ โครงสร้างข้อมูลเหล่านี้มักจะไม่เพียง แต่ทำงานได้อย่างสมบูรณ์ในส่วนต่อประสาน แต่ยังสามารถนำไปใช้ในภาษา Haskell และภาษาที่คล้ายคลึงกันได้
แม้ว่าจะไม่มีเครื่องมือขั้นสูงเหล่านี้ต้นไม้การค้นหาแบบไบนารีที่มีความสมดุลก็ให้การอัปเดตแบบลอการิทึมดังนั้นหน่วยความจำที่ไม่แน่นอนสามารถถูกจำลองด้วยที่แย่ที่สุดเมื่อการลอการิทึมช้าลง
มีตัวเลือกอื่น ๆ ซึ่งอาจถูกพิจารณาว่าเป็นการโกง แต่มีประสิทธิภาพมากโดยคำนึงถึงความพยายามในการดำเนินการและประสิทธิภาพที่แท้จริง ตัวอย่างเช่นประเภทเชิงเส้นหรือชนิดที่ไม่ซ้ำกันอนุญาตให้มีการอัปเดตในสถานที่เป็นกลยุทธ์การใช้งานสำหรับภาษาบริสุทธิ์ทางความคิดโดยการป้องกันไม่ให้โปรแกรมค้างไว้ที่ค่าก่อนหน้า (หน่วยความจำที่จะกลายพันธุ์) นี่เป็นเรื่องทั่วไปที่น้อยกว่าโครงสร้างข้อมูลถาวร: ตัวอย่างเช่นคุณไม่สามารถสร้างบันทึกการเลิกทำอย่างง่ายดายโดยการจัดเก็บสถานะเวอร์ชันก่อนหน้าทั้งหมด มันยังคงเป็นเครื่องมือที่ทรงพลังแม้ว่า AFAIK ยังไม่มีให้ในภาษาหลัก
ตัวเลือกอื่นสำหรับการแนะนำสภาวะที่ไม่แน่นอนให้เข้าสู่การตั้งค่าการทำงานอย่างปลอดภัยคือST
monad ใน Haskell มันสามารถนำมาใช้โดยไม่มีการกลายพันธุ์และยกเว้นunsafe*
ฟังก์ชั่นมันจะทำงานราวกับว่ามันเป็นเพียง wrapper แฟนซีรอบผ่านโครงสร้างข้อมูลถาวรโดยปริยาย (cf. State
) แต่เนื่องจากการใช้กลอุบายของระบบบางประเภทที่บังคับให้ลำดับของการประเมินผลและป้องกันการหลบหนีจึงสามารถนำไปใช้กับการกลายพันธุ์ในสถานที่ได้อย่างปลอดภัยพร้อมผลประโยชน์ด้านประสิทธิภาพทั้งหมด
โครงสร้างที่ไม่แน่นอนที่ถูกหนึ่งคืออาร์กิวเมนต์สแต็ก
ดูการคำนวณแบบแฟคทอเรียลแบบทั่วไป:
(defn fac (n accum)
(if (= n 1)
accum
(fac (- n 1) (* accum n)))
(defn factorial (n) (fac n 1))
ในขณะที่คุณสามารถดูอาร์กิวเมนต์ที่สองจะถูกใช้เป็นสะสมไม่แน่นอนที่จะมีผลิตภัณฑ์ที่เปลี่ยนแปลงอย่างรวดเร็วfac
n * (n-1) * (n-2) * ...
แม้ว่าจะไม่มีตัวแปรที่ไม่แน่นอนอยู่ในสายตา แต่และไม่มีวิธีใดที่จะเปลี่ยนแปลงการสะสมโดยไม่ตั้งใจเช่นจากเธรดอื่น
แน่นอนว่านี่เป็นตัวอย่างที่ จำกัด
คุณสามารถรับลิ้งค์ที่ไม่เปลี่ยนรูปได้โดยการเปลี่ยน head head ราคาถูก (และโดยการขยายส่วนใด ๆ ที่เริ่มต้นจาก head): คุณเพียงแค่สร้าง head head ใหม่ไปยัง node ถัดไปเหมือนกับที่ head เก่าทำ นี้ทำงานได้ดีกับหลายขั้นตอนวิธีการประมวลผลรายการ (อะไรfold
-based)
คุณจะได้รับประสิทธิภาพการทำงานที่ดีงามจาก arrays สมาคมตามเช่นในHAMTs เหตุผลคุณได้รับอาร์เรย์เชื่อมโยงใหม่ที่มีการเปลี่ยนแปลงคู่ค่าคีย์ การใช้งานสามารถแบ่งปันข้อมูลทั่วไปส่วนใหญ่ระหว่างวัตถุเก่าและวัตถุที่สร้างขึ้นใหม่ นี่ไม่ใช่ O (1) โดยปกติคุณจะได้ค่าลอการิทึมอย่างน้อยก็ในกรณีที่แย่ที่สุด ต้นไม้ที่ไม่เปลี่ยนรูปในทางกลับกันมักจะไม่ได้รับค่าปรับใด ๆ เมื่อเปรียบเทียบกับต้นไม้ที่ไม่แน่นอน แน่นอนว่าต้องใช้หน่วยความจำบางส่วนซึ่งอยู่ไกลจากข้อห้าม
แนวทางอื่นอยู่บนพื้นฐานของแนวคิดที่ว่าถ้าต้นไม้ล้มลงในป่าและไม่มีใครได้ยินมันก็ไม่ต้องการให้เกิดเสียง นั่นคือถ้าคุณสามารถพิสูจน์ได้ว่าสถานะการกลายพันธุ์เล็กน้อยไม่เคยออกจากขอบเขตท้องถิ่นคุณสามารถกลายพันธุ์ข้อมูลภายในได้อย่างปลอดภัย
Clojure มีชั่วคราวที่ไม่แน่นอน 'เงา' ของโครงสร้างข้อมูลไม่เปลี่ยนรูปที่ไม่รั่วไหลนอกขอบเขตท้องถิ่น Cleanใช้ Uniques เพื่อให้ได้สิ่งที่คล้ายกัน (ถ้าฉันจำได้อย่างถูกต้อง) สนิมช่วยให้ทำสิ่งที่คล้ายกันด้วยพอยน์เตอร์ที่ไม่ซ้ำกันตรวจสอบแบบคงที่
ref
และ จำกัด ขอบเขตไว้ภายในขอบเขตที่แน่นอน ดูหรือIORef
STRef
และแน่นอนว่ามีTVar
s และMVar
s ที่คล้ายกัน แต่มีความหมายที่เกิดขึ้นพร้อมกันมีสติ (stm สำหรับTVar
s และ mutex ตามMVar
s)
สิ่งที่คุณถามกว้างไปหน่อย O (1) การถอดและเปลี่ยนจากตำแหน่งใด หัวของลำดับหรือไม่ หางหรือไม่ ตำแหน่งโดยพลการ โครงสร้างข้อมูลที่ใช้ขึ้นอยู่กับรายละเอียดเหล่านั้น ที่กล่าวว่า2-3 Finger Treesดูเหมือนเป็นหนึ่งในโครงสร้างข้อมูลถาวรที่หลากหลายที่สุด:
เรานำเสนอต้นไม้ 2-3 นิ้วการทำงานของลำดับถาวรที่รองรับการเข้าถึงจุดสิ้นสุดในเวลาคงที่ตัดจำหน่ายและการต่อกันและแยกในเวลาลอการิทึมเวลาในขนาดของชิ้นเล็ก
( ... )
เพิ่มเติมโดยการกำหนดการดำเนินการแยกในรูปแบบทั่วไปเราได้รับโครงสร้างข้อมูลวัตถุประสงค์ทั่วไปที่สามารถใช้เป็นลำดับคิวลำดับความสำคัญต้นไม้ค้นหาค้นหาคิวลำดับความสำคัญและอื่น ๆ
โดยทั่วไปโครงสร้างข้อมูลถาวรมีประสิทธิภาพลอการิทึมเมื่อเปลี่ยนตำแหน่งโดยพลการ สิ่งนี้อาจจะใช่หรือไม่ใช่ปัญหาเนื่องจากค่าคงที่ในอัลกอริทึม O (1) อาจสูงและการชะลอตัวแบบลอการิทึมอาจจะ "หมกมุ่น" เป็นอัลกอริทึมโดยรวมที่ช้าลง
ที่สำคัญกว่านั้นโครงสร้างข้อมูลถาวรทำให้การใช้เหตุผลของคุณง่ายขึ้นและนั่นควรเป็นโหมดเริ่มต้นของการทำงานของคุณเสมอ คุณควรสนับสนุนโครงสร้างข้อมูลถาวรทุกครั้งที่ทำได้และใช้เฉพาะโครงสร้างข้อมูลที่ไม่แน่นอนเมื่อคุณทำโปรไฟล์และพิจารณาว่าโครงสร้างข้อมูลถาวรนั้นเป็นปัญหาคอขวดของประสิทธิภาพการทำงาน สิ่งอื่นใดคือการปรับให้เหมาะสมก่อนเวลาอันควร