เหตุใดจึงแสดงรายการโครงสร้างข้อมูลของตัวเลือกในภาษาที่ใช้งานได้


45

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



10
@gnat - นี่ไม่ใช่คำถามที่ซ้ำกัน คำตอบที่ได้รับการยอมรับและถูกต้องสำหรับคำถามนั้นก็คือ "เนื่องจากรายการลิงก์ที่ไม่เปลี่ยนรูปแบบช่วยให้สามารถแบ่งปันก้อยระหว่างรายการที่อัปเดตและดั้งเดิมได้" ซึ่งเป็นคำตอบที่ชี้ให้เห็นว่าเป็นส่วนหนึ่งของพื้นหลังของคำถามนี้ ...
Jules

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

ฉัน scala Vector (ซึ่งนำมาใช้เป็นต้นไม้) เป็นที่ต้องการเล็กน้อยในรายการstackoverflow.com/questions/6928327/ในทางปฏิบัติผู้คนส่วนใหญ่ยังคงใช้รายการ (จากสิ่งที่ฉันเห็น)
Akavall

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

คำตอบ:


56

เพราะรายการนั้นง่ายกว่าต้นไม้ (คุณสามารถเห็นสิ่งนี้ได้เล็กน้อยโดยความจริงที่ว่ารายการนั้นเป็นต้นไม้ที่เสื่อมซึ่งทุกโหนดมีลูกเพียงลูกเดียว)

รายการข้อเสียคือโครงสร้างข้อมูลแบบเรียกซ้ำที่ง่ายที่สุดเท่าที่จะเป็นไปได้

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

โปรดสังเกตว่าเช่นใน Clojure ซึ่งมีการออกแบบโครงสร้างข้อมูลสำหรับขนานกระจาย "เมฆ" โลกวันนี้แม้แต่อาร์เรย์ (เรียกว่าเวกเตอร์ใน Clojure) อาจเป็นโครงสร้างข้อมูล "เชิงเส้น" ที่สุดของพวกเขาทั้งหมดจริง ๆ แล้วมีการนำมาใช้เป็น ต้นไม้

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


10
ใช่เวกเตอร์ Clojure ถูกนำมาใช้เป็นต้นไม้ - แต่มันก็สังเกตได้ว่ามันเป็นความพยายามแมปอาร์เรย์แฮชไม่ใช่ไบนารีมาตรฐานdata Tree a = Leaf a | Branch a (Tree a) (Tree a)ของคุณ นี่เป็นการตอกย้ำข้อโต้แย้ง "ความเรียบง่าย" ของคุณ
wchargin

1
เวกเตอร์ถาวรของ FWIW Clojure ถูกนำมาใช้เป็น (ในขณะที่ @wchargin ชี้ให้เห็นค่อนข้างซับซ้อน) ต้นไม้สำหรับการเข้าถึงอย่างรวดเร็ว (ลอการิทึมที่มีฐานขนาดใหญ่) และอัปเดตองค์ประกอบโดยพลการไม่ใช่การทำงานแบบขนานต่อกันเท่านั้น ระดับ). ภาษา FP อื่น ๆ มีตัวเลือกเดียวกัน (บางครั้งมีต้นไม้หลายชนิด) เมื่อพวกเขาต้องการทั้งสองอย่าง (เช่น Haskell's Sequenceหรือ Scala's Vector) แต่ไม่ใช้ต้นไม้เมื่อพวกเขาต้องการเพียงอ่านเพราะพวกเขาสามารถบรรลุในเวลาคงที่ที่แท้จริง (เช่น Haskell Vectorหรือ F # ผ่าน. Net ImmutableArray)
badcook

1
เช่นการpmapping เวกเตอร์ใน Clojure ยังคงเข้าถึงแต่ละองค์ประกอบตามลำดับ โครงสร้างต้นไม้ของเวกเตอร์โดยทั่วไปจะถูกซ่อนจากผู้ใช้
badcook

5

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

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


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

@Jules อย่างไรก็ตามโปรแกรมการทำงานได้รับการพัฒนาและได้รับอิทธิพลอย่างมากจากภาษาเช่น LISP เห็นได้ชัดว่ามันเป็นไปได้ที่จะทำให้การทำซ้ำรายการทั้งหมดนี้มีประสิทธิภาพมากขึ้นโดยใช้อาร์เรย์ภายใต้ประทุนหรือเพื่อเพิ่มน้ำตาลวากยสัมพันธ์ที่ซ่อนอยู่ในรายการ แต่การทำงานของโปรแกรมล้วนๆ นอกจากนี้ Haskell ยังเป็นภาษาที่ค่อนข้างใหม่ (อายุน้อยกว่า LISP 32 ปี) ซึ่งเพิ่มความคิดอื่น ๆ อีกเล็กน้อยน้ำตาล syntactic และอื่น ๆ เพื่อสไตล์การทำงานที่บริสุทธิ์ ฉันคิดว่าการตัดสินการเขียนโปรแกรมฟังก์ชั่นโดยการตัดสิน Haskell เป็นเหมือนการผสมเครื่องตัดสินโดยการตัดสิน thermomix ...
cmaster

2
@cmaster ในขณะที่ Haskell มีอายุน้อยกว่าก็ยังมีอายุ 27 ปีและมีอิทธิพลต่อหลายภาษา (รวมถึง Python, Java และ C # เพื่อบอกชื่อผู้มีอิทธิพลน้อย) การตัดสินการเขียนโปรแกรมฟังก์ชั่นโดย LISP นั้นเหมือนกับการตัดสินการเขียนโปรแกรมที่จำเป็นโดย ALGOL ซึ่งทั้งคู่ต่างมาไกลเกินกว่าจะจำไม่ได้ ตกลง. เสียงกระเพื่อมยังคงมีเนื้อหาที่เกี่ยวข้อง แต่ฉันจะไม่คิดว่ามัน 'สำคัญ' และคิดถึงมากในภายหลังรวมถึงประเภท ML
Maciej Piechotka

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

@MaciejPiechotka ไม่ว่าจะเป็น Python, Java หรือ C # เป็นภาษาที่ใช้งานได้พวกมันจำเป็นและเพิ่มคุณสมบัติบางอย่างที่ได้รับแรงบันดาลใจจากการเขียนโปรแกรมที่ใช้งานได้ เมื่อคุณเปลี่ยนสถานะแล้วคุณจะอยู่ในขอบเขตของการเขียนโปรแกรมที่จำเป็นไม่ใช่การทำงาน ฉันเห็นด้วยกับคุณว่า LISP นั้นไม่สำคัญ
cmaster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.