ภาษาโปรแกรมที่ใช้งานได้จริงจัดการกับข้อมูลที่เปลี่ยนแปลงอย่างรวดเร็วอย่างไร


22

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


2
สำหรับพวกเราที่ไม่ค่อยคุ้นเคยกับภาษาการเขียนโปรแกรมที่ใช้งานได้จริงคุณผอมคุณสามารถให้พื้นฐานเพิ่มเติมเล็กน้อยเพื่อให้เราเข้าใจว่าปัญหาของคุณคืออะไร?
FrustratedWithFormsDesigner

4
@FrustratedWithFormsDesigner ภาษาการเขียนโปรแกรมที่ใช้งานได้จริงต้องการตัวแปรทั้งหมดที่ไม่เปลี่ยนรูปซึ่งต้องใช้โครงสร้างข้อมูลที่สร้างเวอร์ชั่นใหม่ของตัวเองเมื่อ "แก้ไข"
Doval

5
คุณรู้หรือไม่ว่างานของ Okasaki เกี่ยวกับโครงสร้างข้อมูลที่ใช้งานได้จริง

2
ความเป็นไปได้อย่างหนึ่งคือการกำหนด monad สำหรับข้อมูลที่ไม่แน่นอน (ดูเช่นhaskell.org/ghc/docs/4.08/set/sec-marray.html ) ด้วยวิธีนี้ข้อมูลที่ไม่แน่นอนจะได้รับการปฏิบัติเช่นเดียวกับ IO
Giorgio

1
@CodesInChaos: อย่างไรก็ตามโครงสร้างที่ไม่เปลี่ยนรูปแบบดังกล่าวมักจะมีค่าใช้จ่ายมากขึ้นกว่าอาร์เรย์ที่เรียบง่าย เป็นผลให้มีความแตกต่างในทางปฏิบัติเป็นอย่างมาก ซึ่งเป็นเหตุผลว่าทำไมภาษาใด ๆ ที่ใช้งานได้อย่างหมดจดซึ่งมีจุดมุ่งหมายที่การเขียนโปรแกรมวัตถุประสงค์ทั่วไปควรมีวิธีใช้โครงสร้างที่เปลี่ยนแปลงได้ในบางวิธีที่ปลอดภัยซึ่งเข้ากันได้กับความหมายที่บริสุทธิ์ STmonad ใน Haskell ทำอย่างนี้เนี่ย
leftaroundabout

คำตอบ:


32

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

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

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

ตัวเลือกอื่นสำหรับการแนะนำสภาวะที่ไม่แน่นอนให้เข้าสู่การตั้งค่าการทำงานอย่างปลอดภัยคือSTmonad ใน Haskell มันสามารถนำมาใช้โดยไม่มีการกลายพันธุ์และยกเว้นunsafe*ฟังก์ชั่นมันจะทำงานราวกับว่ามันเป็นเพียง wrapper แฟนซีรอบผ่านโครงสร้างข้อมูลถาวรโดยปริยาย (cf. State) แต่เนื่องจากการใช้กลอุบายของระบบบางประเภทที่บังคับให้ลำดับของการประเมินผลและป้องกันการหลบหนีจึงสามารถนำไปใช้กับการกลายพันธุ์ในสถานที่ได้อย่างปลอดภัยพร้อมผลประโยชน์ด้านประสิทธิภาพทั้งหมด


อาจเป็นสิ่งที่ควรค่าแก่การกล่าวถึง Zippers ซึ่งทำให้คุณมีความสามารถในการเปลี่ยนแปลงอย่างรวดเร็วโดยเน้นที่รายการหรือ
แผนผัง

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

ยุติธรรมพอไม่ได้ติดตามลิงก์
jk

9

โครงสร้างที่ไม่แน่นอนที่ถูกหนึ่งคืออาร์กิวเมนต์สแต็ก

ดูการคำนวณแบบแฟคทอเรียลแบบทั่วไป:

(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 เพื่อให้ได้สิ่งที่คล้ายกัน (ถ้าฉันจำได้อย่างถูกต้อง) สนิมช่วยให้ทำสิ่งที่คล้ายกันด้วยพอยน์เตอร์ที่ไม่ซ้ำกันตรวจสอบแบบคงที่


1
+1 เช่นกันสำหรับการกล่าวถึงประเภทที่ไม่ซ้ำใน Clean
Giorgio

@ 9000 ฉันคิดว่าฉันได้ยินว่า Haskell มีบางสิ่งบางอย่างที่คล้ายคลึงกับของชั่วคราวของ Clojure - มีคนแก้ไขฉันถ้าฉันผิด
paul

@ พอล: ฉันมีความรู้คร่าวๆเกี่ยวกับ Haskell ดังนั้นหากคุณสามารถให้ข้อมูลของฉัน (อย่างน้อยคำหลักที่ Google) ฉันมีความสุขรวมถึงการอ้างอิงคำตอบ
9000

1
@ พอลฉันไม่แน่ใจ แต่แฮสเค็ลล์มีวิธีการสร้างบางสิ่งที่คล้ายกับ ML refและ จำกัด ขอบเขตไว้ภายในขอบเขตที่แน่นอน ดูหรือIORef STRefและแน่นอนว่ามีTVars และMVars ที่คล้ายกัน แต่มีความหมายที่เกิดขึ้นพร้อมกันมีสติ (stm สำหรับTVars และ mutex ตามMVars)
Daniel Gratzer

2

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

เรานำเสนอต้นไม้ 2-3 นิ้วการทำงานของลำดับถาวรที่รองรับการเข้าถึงจุดสิ้นสุดในเวลาคงที่ตัดจำหน่ายและการต่อกันและแยกในเวลาลอการิทึมเวลาในขนาดของชิ้นเล็ก

( ... )

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

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

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

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