簡體   English   中英

大小差異來自何處?

[英]Where does the difference in size come from?

我創建了一個trie來將所有單詞(非定義)存儲在英語詞典中。 這樣做的目的是讓我可以得到在給定范圍內僅包含​​字母的所有單詞。

包含所有單詞的文本文件大約為2.7 mb,但是在創建樹並將其使用pickle寫入文件后,文件的大小為> 33 mb。

大小上的差異從何而來? 我以為我可以節省空間,因為不需要為不同的單詞存儲同一字母的多個副本,例如對於單詞app和apple我只需要5個節點,對於-> p-> p-> l-> e 。

我的代碼如下:

import pickle

class WordTrieNode:
    def __init__(self, nodeLetter='', parentNode=None, isWordEnding=False):
        self.nodeLetter = nodeLetter
        self.parentNode = parentNode
        self.isWordEnding = isWordEnding
        self.children = [None]*26 # One entry for each lowercase letter of the alphabet

    def getWord(self):
        if(self.parentNode is None):
            return ''

        return self.parentNode.getWord() + self.nodeLetter

    def isEndOfWord(self):
        return self.isWordEnding

    def markEndOfWord():
        self.isWordEnding = True

    def insertWord(self, word):
        if(len(word) == 0):
            return

        char = word[0]
        idx = ord(char) - ord('a')
        if(len(word) == 1):
            if(self.children[idx] is None):
                node = WordTrieNode(char, self, True)
                self.children[idx] = node
            else:
                self.children[idx].markEndOfWord()
        else:
            if(self.children[idx] is None):
                node = WordTrieNode(char, self, False)
                self.children[idx] = node
                self.children[idx].insertWord(word[1:])
            else:
                self.children[idx].insertWord(word[1:])

    def getAllWords(self):
        for node in self.children:
            if node is not None:
                if node.isEndOfWord():
                    print(node.getWord())
                node.getAllWords()

    def getAllWordsInRange(self, low='a', high='z'):
        i = ord(low) - ord('a')
        j = ord(high) - ord('a')
        for node in self.children[i:j+1]:
            if node is not None:
                if node.isEndOfWord():
                    print(node.getWord())
                node.getAllWordsInRange(low, high)



def main():

    tree = WordTrieNode("", None, False)

    with open('en.txt') as file:
        for line in file:
            tree.insertWord(line.strip('\n'))
    with open("treeout", 'wb') as output:
        pickle.dump(tree, output, pickle.HIGHEST_PROTOCOL)

    #tree.getAllWordsInRange('a', 'l')
    #tree.getAllWords()
if __name__ == "__main__":
    main()

特里的節點很大,因為它們存儲着所有可能的下一個字母的鏈接。 正如您在代碼中看到的那樣,每個節點都包含26個鏈接(子代)的列表。

可能會有更緊湊的方案( https://en.wikipedia.org/wiki/Trie#Compressing_tries ),但代價是更加復雜且速度較慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM