我正在尝试将某些数据结构实现为Python中的类(链接列表,二进制树,尝试等)。对于其中的某些结构,我可以尝试将它们实现为dict-of-dict(例如trie为其子级嵌套了层),也可以将它们实现为具有“ next”变量,该变量包含相同的另一个实例化。目的。
我想知道与将所有子数据存储在成员变量中相比,递归数据结构的优缺点是什么?有速度或内存优势吗?更好的缓存?可读性?
下面是一些示例代码,它们说明了我在说什么,但是我对理论上的好处比对我的伪代码的批评更感兴趣:)
class Trie:
def __init__(self) -> None:
self._trie = {}
def insert(self, text: str) -> None:
trie = self._trie
for char in text:
if char not in trie:
trie[char] = {}
trie = trie[char]
trie["END"] = True
def search(self, prefix: str) -> bool:
trie = self._trie
for char in prefix:
if char not in trie:
return False
trie = trie[char]
return True
class RecursiveTrie:
def __init__(self) -> None:
self.children: List[Optional[RecursiveTrie]] = [None] * 26
self.end_of_word = False
def insert(self, key: str) -> None:
"""
If not present, inserts key into trie.
If the key is prefix of trie node, just marks leaf node.
"""
if not key:
self.end_of_word = True
return
index = self.char_to_index(key[0])
if self.children[index] is None:
self.children[index] = RecursiveTrie()
child = self.children[index]
child.insert(key[1:])
def search(self, key: str) -> bool:
""" Search key in the trie. Returns true if key is present in trie. """
if not key:
return True
index = self.char_to_index(key[0])
if self.children[index] is None:
return False
return self.children[index].search(key[1:])
IMO真正采用两种方法中的哪一种取决于您要编写的代码是实际的生产代码还是练习。
对于生产代码,您应该使用第一个版本,它较小且易于阅读。它被视为dict
基本的砖块(就像在Python中一样),并且嵌套的dict完全没有问题(考虑到python中的每个对象属性都在dict
...中,使用指向另一个实例的成员不使用dict不会)乍一看似乎是个好主意)。
为了理解尝试,第二个版本(不明确地)不依赖于字典,而是用C甚至C ++编写的,与之相比,数组可能有意义std::map
(应通过对真实数据和真实生产进行剖析来证明)硬件,今天的CPU太复杂了,无法预测复杂算法的性能。如果将来您需要使用低级语言来实现Trie或Trie的变体,那么这些知识将非常有用。
生产型python软件中的第二个版本使将来的同事和/或您自己的生活更加艰难。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句