函数式编程中的数据结构


11

我目前正在使用LISP(尤其是Scheme和Clojure),并且想知道函数式编程语言中如何处理典型的数据结构。

例如,假设我想使用图形寻路算法解决问题。通常如何用一种功能编程语言(主要是对可以应用于LISP的纯功能样式感兴趣)来表示该图?我是否会完全忘记图并以其他方式解决问题?

Answers:


14

自从我在LISP工作以来已经有一段时间了,但是我记得,基本的非原子结构只是列表。其他一切都基于此。因此,您可以有一个原子列表,其中每个原子都是一个节点,然后是将节点连接到其他节点的边的列表。我敢肯定,还有其他方法可以做到这一点。

也许是这样的:

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

可以给出这样的图形:

a <-> b <-> 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搜索短语“ lisp图结构”找到)


4
这有点晚了,但是我想提醒我,“其他所有内容都基于[list]”会误导您。Common Lisp,Scheme和Clojure都具有矢量,映射,字符串以及结构/类,而不是建立在列表顶部。我们编写的用于创建它们的代码通常是一个列表,例如(make-array'(2 2):initial-element 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指向权重为3的:b和:c权重为4的:b指向权重为1的:a::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  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.