โครงสร้างข้อมูลในการโปรแกรมเชิงฟังก์ชัน


11

ขณะนี้ฉันกำลังเล่นกับ LISP (โดยเฉพาะ Scheme และ Clojure) และฉันสงสัยว่าโครงสร้างข้อมูลทั่วไปนั้นจัดการกับภาษาโปรแกรมที่ใช้งานได้อย่างไร

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

คำตอบ:


14

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

อาจจะเป็นสิ่งนี้:

(
  (a (b c)),
  (b (a c)),
  (c (a b d)),
  (d (c))
)

สามารถให้กราฟดังนี้:

ค่า <-> ข <-> C <-> d
^ ^
| |
+ --------- +

หากคุณต้องการได้รับแฟนซีคุณสามารถเพิ่มน้ำหนักได้เช่นกัน:

(
  (a (b 1.0 c 2.0)),
  (b (a 1.0 c 1.0)),
  (c (a 1.3 b 7.2 d 10.5)),
  (d (c -10.5))
)

คุณอาจสนใจสิ่งนี้: CL-Graph (ค้นพบโดย google - ค้นหาวลี "โครงสร้างกราฟเสียงกระเพื่อม")


4
นี่มันช้าไปหน่อย แต่ฉันคิดว่าฉันควรเตือนว่า "ทุกอย่างที่อยู่บน [รายการ]" กำลังทำให้เข้าใจผิด Common Lisp, Scheme และ Clojure ล้วนมีเวกเตอร์, แผนที่, สตริง, รวมถึงโครงสร้าง / คลาส, ไม่ได้สร้างอยู่ด้านบนของรายการ; รหัสเราเขียนการสร้างพวกเขาโดยทั่วไปคือรายการเช่น (แต่งหน้าอาร์เรย์ (2 2): เริ่มต้นองค์ประกอบ 0) แต่โครงสร้างข้อมูลไม่ได้ดำเนินการโดยใช้รายการ
coredump

3

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

คุณสามารถสร้างประเภทข้อมูลนามธรรมใน Lisp ตัวอย่างเช่นสำหรับกราฟคุณอาจต้องการฟังก์ชั่นสองอย่าง:

(define (get-vertices graph) ;; gets all the vertices from a graph
  ...)

(define (get-edges graph) ;; gets all the edges from a graph
  ...)

(define (get-weight vertex-from vertex-to) ;; get the weight of a specific vertex
  ...)

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

ที่สำคัญคือเพื่อให้แน่ใจว่ารหัสที่ใช้กราฟเพียงใช้อินเตอร์เฟซกราฟและไม่สามารถเข้าถึงการใช้งานพื้นฐาน สิ่งนี้จะทำให้รหัสไคลเอนต์ง่ายขึ้นเนื่องจากไม่มีการแยกจากการใช้งานจริง


2

มันจะขึ้นอยู่กับว่ากราฟของคุณกำกับ / ไม่ระบุทิศทาง, ถ่วงน้ำหนัก / ไม่ถ่วงน้ำหนัก แต่วิธีหนึ่งในการแสดงกราฟกำกับน้ำหนัก (ซึ่งจะเป็นทั่วไปมากที่สุด) คือแผนที่ของแผนที่ (ใน Clojure)

{
 :a {:b 3 :c 4} 
 :b {:a 1} 
 :c {}
}

จะแสดงแผนที่พร้อมโหนด: a: b และ: c : a ชี้ไปที่: b มีน้ำหนัก 3 และ: c มีน้ำหนัก 4: b ชี้ไปที่: a มีน้ำหนัก 1: c ไม่ได้ชี้ไปที่อะไรเลย


1

ใน Common LISP ถ้าฉันต้องการแสดงต้นไม้ฉันจะใช้รายการ (ถ้าเป็นเพียงการแฮ็คอย่างรวดเร็ว) หรือกำหนดคลาสต้นไม้ (หรือ struct แต่คลาสมีปฏิสัมพันธ์ที่ดีกับฟังก์ชันทั่วไปดังนั้นทำไมไม่) .

(defclass tree ()
  ((node :accessor node :initarg :node)
   (children :accessor children :initarg :children)))

ถ้าฉันต้องการต้นไม้ตามตัวอักษรในรหัสฉันอาจจะกำหนดmake-treeฟังก์ชั่นที่ใช้แสดงรายการต้นไม้ที่ฉันต้องการและเปลี่ยนเป็นต้นไม้ของวัตถุต้นไม้


-2

ใน Haskell รายการนั้นเป็นโครงสร้างข้อมูลพื้นฐานและหากคุณต้องการโครงสร้างข้อมูลขั้นสูงมากขึ้นคุณมักจะใช้โครงสร้างแบบเรียกซ้ำแบบทรีเช่นต้นไม้เป็นโมฆะหรือโหนดและต้นไม้สองต้น

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