Cấu trúc dữ liệu trong lập trình chức năng


11

Tôi hiện đang chơi với LISP (đặc biệt là Scheme và Clojure) và tôi tự hỏi làm thế nào các cấu trúc dữ liệu điển hình được xử lý trong các ngôn ngữ lập trình chức năng.

Ví dụ: giả sử tôi muốn giải quyết vấn đề bằng thuật toán tìm đường biểu đồ. Làm thế nào người ta thường đi về việc biểu diễn đồ thị đó bằng ngôn ngữ lập trình chức năng (chủ yếu quan tâm đến phong cách chức năng thuần túy có thể áp dụng cho LISP)? Tôi sẽ chỉ quên đồ thị hoàn toàn và giải quyết vấn đề theo cách khác?

Câu trả lời:


14

Đã được một thời gian kể từ khi tôi làm việc trong LISP, nhưng khi tôi nhớ lại, cấu trúc phi nguyên tử cơ bản là một danh sách. Mọi thứ khác đều dựa trên điều đó. Vì vậy, bạn có thể có một danh sách các nguyên tử trong đó mỗi nguyên tử là một nút theo sau là danh sách các cạnh kết nối nút với các nút khác. Tôi chắc chắn có những cách khác để làm điều đó quá.

Có lẽ một cái gì đó như thế này:

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

có thể đưa ra một biểu đồ như thế này:

a <-> b <-> c <-> d
^ ^
| |
+ --------- +

Nếu bạn muốn có được sự ưa thích, bạn cũng có thể thêm trọng lượng cho nó:

(
  (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))
)

Bạn cũng có thể quan tâm đến điều này: CL-Graph (được tìm thấy bởi google - tìm kiếm cụm từ "lisp graph struct")


4
Điều này hơi muộn, nhưng tôi nghĩ rằng tôi nên cảnh báo rằng "Mọi thứ khác đều dựa trên [danh sách]" là sai lệch. Tất cả Lisp, Scheme và Clojure chung đều có vectơ, bản đồ, chuỗi, cũng như các cấu trúc / lớp, không được xây dựng trên đầu danh sách; các đang chúng tôi viết để tạo ra chúng thường là một danh sách, ví dụ (make-mảng '(2 2): ban đầu phần tử 0), nhưng các cấu trúc dữ liệu không được thực hiện sử dụng danh sách.
coredump

3

Các ngôn ngữ chức năng xử lý các cấu trúc dữ liệu giống như các ngôn ngữ phi chức năng thực hiện: bằng cách tách giao diện khỏi thực hiện, tạo các kiểu dữ liệu trừu tượng.

Bạn có thể tạo các kiểu dữ liệu trừu tượng trong Lisp. Ví dụ, đối với biểu đồ, bạn có thể muốn có một vài hàm:

(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
  ...)

Khi bạn đã tạo giao diện đó thành biểu đồ, bạn có thể triển khai cấu trúc dữ liệu thực tế theo nhiều cách khác nhau, có thể tối ưu hóa các yếu tố như hiệu quả lập trình, tính linh hoạt và hiệu quả tính toán.

Điều quan trọng là đảm bảo rằng mã sử dụng biểu đồ chỉ sử dụng giao diện biểu đồ và không truy cập vào triển khai cơ bản. Điều này sẽ giữ cho mã máy khách đơn giản hơn khi được tách rời khỏi triển khai thực tế.


2

Vâng, nó sẽ phụ thuộc vào việc biểu đồ của bạn được định hướng / không bị chặn, có trọng số / không có trọng số nhưng một cách để biểu thị một biểu đồ có hướng, có trọng số (sẽ là tổng quát nhất) với bản đồ của bản đồ (trong Clojure)

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

sẽ biểu diễn một bản đồ với các nút: a: b và: c. : a trỏ tới: b có trọng số 3 và: c có trọng số 4 .: b điểm tới: a có trọng lượng 1 .: c không chỉ ra bất cứ điều gì.


1

Trong Common Lisp, nếu tôi cần đại diện cho một cây, tôi sẽ sử dụng một danh sách (nếu đó chỉ là một bản hack nhanh) hoặc định nghĩa một lớp cây (hoặc struct, nhưng các lớp tương tác tốt với các hàm chung, vậy tại sao không) .

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

Nếu tôi cần cây theo nghĩa đen trong mã, có lẽ tôi cũng xác định một make-treehàm lấy biểu thị danh sách của cây tôi muốn và biến nó thành cây của các đối tượng cây.


-2

Trong Haskell, danh sách là cấu trúc dữ liệu cơ bản và nếu bạn muốn một cấu trúc dữ liệu nâng cao hơn, bạn thường sử dụng các cấu trúc đệ quy như một cây là null hoặc một nút và hai cây

data Tree a = Null | Node Tree a Tree  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.