私はLispの初心者で、トライのクラスを定義し、スクラブル辞書全体を読み込むパッケージを作成しようとしています。構造体はノードとして機能します。各ノードには、それから派生した(他のサブトリーにつながる)文字を追跡する関連付けリストがあります。
これがクラスの私のコードです
(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))))
辞書全体を読み込もうとすると、スタックオーバーフローが発生します。スクラブル辞書には10万語以上あり、6000語で失敗しています...メモリ使用量に問題がありますが、何がわからないようです。
これらの定義で私が行っていることで、メモリに関して本質的に高価なものはありますか?トライノードをクラスではなく構造体にしてみたところ、同様の結果が得られました。辞書から単語を追加するための再帰的アルゴリズムもありましたが、それも同様に悪かったです。
私はこれに何時間も苦労してきました、そして私は少しイライラしています...