当前位置: 首页 > 知识库问答 >
问题:

LISP-TRIE数据结构中函数(内存)的优化

朱高超
2023-03-14

我是一个lisp初学者,我试图编写一个包,为trie定义一个类,并在其中读取拼字词典的全部内容。该结构充当一个节点,每个节点都有一个关联列表,该列表跟踪来自它的字母(导致其他子区)。

下面是我的类代码

(DEFCLASS n-trie ()
  ((word :accessor word
         :initform 'nil
         :initarg :word)
   (word-count :accessor wcount
               :initform 0
               :initarg :wcount)
   (next-letters :accessor next-letters
                 :initform 'nil
                 :initarg :next-letters)))

这是我的添加单词函数

(defun add-word (string trie) ;;iterative method for looping through string
  (let ((s (coerce string 'list))
        (tri trie))
    (dolist (item s)
      (cond
       ((assoc item (next-letters tri))
        (incf (wcount tri))
        (setf tri (cdr (assoc item (next-letters tri)))))
       (t
        (incf (wcount tri))
        (setf (next-letters tri) (acons item (make-instance 'n-trie) (next-letters tri)))
        (setf tri (cdr (assoc item (next-letters tri)))))))
    (setf (word tri) string)))

下面是打开我的文件(拼字字典)并读取每一行的函数

(defun read-words (file trie)
  (let((str (open file)))
    (labels ((rec (tri)
                  (let ((line (read-line str nil nil)))
                    (cond 
                     (line (add-word line tri)
                           (rec tri))
                     (t (close str)
                        trie)))))
      (rec trie))))

每当我试图加载整个字典时,都会出现堆栈溢出。拼字字典里有100k多个单词,但它在6000个时失败了……我的记忆使用情况出了问题,但我似乎不知道是什么。

我在这些定义中所做的事情是不是固有的内存开销?我尝试将trie节点作为一个结构而不是一个类,得到了类似的结果。我也有一个递归算法来从字典中添加一个单词,但它同样糟糕。

我已经为此挣扎了几个小时,我有点沮丧...

共有1个答案

郑和泰
2023-03-14

我首先要更改的是函数read-words。它使用尾部递归,看起来像在Scheme中。这在普通的Lisp中是不地道的。使用with-open-file打开文件并使用循环构造读取行。如果公共Lisp系统没有优化尾递归,则此递归已经在大型文本文件上造成堆栈溢出。

所以:

>

  • 不要在不必要的地方使用尾递归,并且您知道您的CL实现实际上支持并理解它。例如,高调试模式通常会阻止尾递归优化

    使用with-open-file。不要使用打开/关闭

    使用if而不是cond-尤其是在处理正常的true/false谓词时。

  •  类似资料:
    • 问题内容: 是否有任何库或文档/链接提供了有关在Java中实现Trie数据结构的更多信息? 任何帮助将是巨大的! 谢谢。 问题答案: 您可以阅读Java Trie 或查看trie。

    • 我正在用Python实现一个Trie。到目前为止,我遇到了两种不同的方法来实现它: -存储字符 -存储单词结尾(true或false) -存储具有当前前缀的单词数 我们派生出这本词典: 哪一种是高效的、标准的数据结构,既能有效地存储内存,又能快速地进行字的大数据集上的遍历和其他trie操作?

    • 到目前为止,我们已经讨论了为了实现文件系统而需要存在于硬盘上的数据结构。 在这里,我们将了解要实现文件系统需要存在于内存中的数据结构。 内存数据结构用于文件系统管理以及通过缓存提高性能。 该信息在安装时间加载并在弹出时丢弃。 1. 内存安装表 内存中安装表包含正在安装到系统的所有设备的列表。 每当连接维护到设备时,其输入将在安装表中完成。 2. 内存目录结构缓存 这是CPU最近访问的目录列表。列表

    • 7.4.1. 设计选择 7.4.2. 使你的数据尽可能小 7.4.3. 列索引 7.4.4. 多列索引 7.4.5. MySQL如何使用索引 7.4.6. MyISAM键高速缓冲 7.4.7. MyISAM索引统计集合 7.4.8. MySQL如何计算打开的表 7.4.9. MySQL如何打开和关闭表 7.4.10. 在同一个数据库中创建多个表的缺陷 7.4.1. 设计选择 MySQL将行数据和索

    • 主要内容:图存储结构基本常识,图存储结构的分类我们知道,数据之间的关系有 3 种,分别是 "一对一"、"一对多" 和 "多对多",前两种关系的数据可分别用 线性表和树结构存储,本节学习存储具有"多对多"逻辑关系数据的结构—— 图存储结构。 图 1 图存储结构示意图 图 1 所示为存储 V1、V2、V3、V4 的图结构,从图中可以清楚的看出数据之间具有的"多对多"关系。例如,V1 与 V4 和 V2 建立着联系,V4 与 V1 和 V3 建立着

    • 主要内容:树的结点,子树和空树,结点的度和层次,有序树和无序树,森林,树的表示方法,总结之前介绍的所有的 数据结构都是 线性存储结构。本章所介绍的树结构是一种非线性存储结构,存储的是具有“一对多”关系的数据元素的集合。                                                                          (A)