Fonksiyonel programlamada veri yapıları


11

Şu anda LISP (özellikle Scheme ve Clojure) ile oynuyorum ve tipik veri yapılarının fonksiyonel programlama dillerinde nasıl ele alındığını merak ediyorum.

Örneğin, bir grafik yol bulma algoritması kullanarak bir sorunu çözmek istediğimi varsayalım. Bir kişi tipik olarak bu grafiği fonksiyonel bir programlama dilinde temsil eder (öncelikle LISP'ye uygulanabilen saf fonksiyonel stille ilgilenir)? Grafikleri tamamen unutabilir miyim ve sorunu başka bir şekilde çözebilir miyim?

Yanıtlar:


14

LISP'de çalıştığımdan bu yana bir süre geçti, ama hatırladığım gibi, atomik olmayan temel yapı bir liste. Diğer her şey buna dayanıyor. Böylece, her atomun bir düğüm olduğu bir atomlar listesi ve ardından düğümü diğer düğümlere bağlayan kenarların bir listesi olabilir. Eminim bunu yapmanın başka yolları da vardır.

Belki böyle bir şey:

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

böyle bir grafik verebilir:

a <-> b <-> C <-> D
^ ^
| |
+ --------- +

Eğer süslemek istiyorsanız, ona ağırlık da ekleyebilirsiniz:

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

Ayrıca ilginizi çekebilir: CL-Graph (google-search by "lisp graph structure" ifadesi bulundu)


4
Bu biraz geç, ama sanırım "Her şey [listeye dayalıdır” yanıltıcıdır. Ortak Lisp, Şema ve Clojure'un hepsinde listeler üzerine inşa edilmeyen vektörler, haritalar, dizeler ve yapılar / sınıflar bulunur; Kod genellikle bunları oluşturmak için geç bir listesi, örneğin (marka dizi '(2 2): Başlangıç eleman 0)' dir, ancak veri yapısı listeleri kullanarak uygulanmamaktadır.
coredump

3

İşlevsel diller, veri yapıları ile işlevsel olmayan dillerin yaptığı gibi ilgilenir: arayüzü uygulamadan ayırarak, soyut veri türleri oluşturarak.

Lisp'de soyut veri türleri oluşturabilirsiniz. Örneğin, bir grafik için birkaç işlev isteyebilirsiniz:

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

Bu arabirimi bir grafiğe oluşturduktan sonra, gerçek veri yapılarını birçok farklı şekilde uygulayarak, muhtemelen programcı verimliliği, esneklik ve hesaplama verimliliği gibi faktörleri optimize edebilirsiniz.

Anahtar, grafik kullanan kodun yalnızca grafik arabirimini kullandığından ve temeldeki uygulamaya erişmediğinden emin olmaktır . Bu, gerçek uygulamadan ayrıldığı için istemci kodunu daha basit tutacaktır.


2

Grafiğinizin yönlendirilmiş / yönlendirilmemiş, ağırlıklı / ağırlıksız olmasına bağlı olacaktır, ancak yönlendirilmiş, ağırlıklı bir grafiği (en genel olanı) temsil etmenin bir yolu (bir harita) (Clojure'da)

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

a: b ve: c düğümlü bir haritayı temsil eder. : a puan b: 3 ağırlık ve c c ağırlık 4: b puan: a ağırlık 1 a: c hiçbir şeye işaret etmez.


1

Common Lisp'de, bir ağacı temsil etmem gerekirse, ya bir liste kullanırdım (sadece hızlı bir kesmek içinse) ya da bir ağaç sınıfı tanımlarım (ya da yapı, ama sınıflar genel işlevlerle iyi etkileşime girer, neden olmasın) .

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

Koddaki değişmez ağaçlara ihtiyacım varsa, muhtemelen make-treeistediğim ağacın bir liste temsilini alan ve bir ağaç nesneleri ağacına dönüştüren bir işlev de tanımlarım .


-2

Haskell'de liste temel veri yapısıdır ve daha gelişmiş bir veri yapısı istiyorsanız, genellikle ağaç null veya düğüm ve iki ağaç gibi özyinelemeli yapıları kullanırsınız.

data Tree a = Null | Node Tree a Tree  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.