剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年08月03日 09:35:13, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
关于字典树的实现,已经有非常多的博文涉及到了。但基本都是用内嵌数组/列表实现的。
本博文是它的递归实现。
<span style="font-size:18px;">### # @usage 字典树 # @author mw # @date 2016年08月02日 星期二 08:56:34 # @param # @return # ### class Trie: class TrieNode: def __init__(self,item,next = None, follows = None): self.item = item self.next = next self.follows = follows def __str__(self): return str(self.item); def getnext(self): return self.next; def setnext(self, next): self.next = next; def getfollows(self): return self.follows; def setfollows(self, follows): self.follows = follows; def getitem(self): return self.item; def setitem(self, item): self.item = item; def __iter__(self): yield self.item; if (self.follows != None): for x in self.follows: yield x; def iternext(self): yield self.item; if (self.next != None): for x in self.next.iternext(): yield x; #从两个方向观察节点信息,一是从它的后续看,这是看一个单词 #另一个是从它的兄弟看,这是在这个点的各分支 def info(self, direction = 0): s = ''; if direction == 0: for x in self: s += str(x)+'-->'; else: for x in self.iternext(): s += str(x)+'-->'; print(s); def __init__(self): self.start = Trie.TrieNode('^', None, None); def insert(self,item): self.start = Trie.__insert(self.start,item) def __contains__(self,item): return Trie.__contains(self.start,item) #生成诩根所在的结点 def __genNode(item): if (len(item) == 1): return Trie.TrieNode(item[0], None, None); elif (len(item) > 1): return Trie.TrieNode(item[0], None, Trie.__genNode(item[1:])); else: return None; def __insert(node,item): # This is the recursive insert function. if (item == None or item == ''): return None; elif (node == None): return Trie.__genNode(str(item)); elif (node.item == item[0]): node.setfollows(Trie.__insert(node.getfollows(), item[1:])); else: node.setnext(Trie.__insert(node.getnext(), item)); return node; def __contains(node, item): # This is the recursive membership test. #单词结尾用'$'分隔,当然,如果用其它分隔符,此处必须更改item+'$' if Trie.__getNode(node, item) != None: return True; else: return False; #一般都是从字典的根结点开始遍历才有意义 def getNode(self, node, item): return Trie.__getNode(node, item); #找到某一节点 def __getNode(node, item): if item == None or item == '': return None; elif node == None: return None; elif node.item != item[0]: return Trie.__getNode(node.next, item); else: if (len(item) > 1): return Trie.__getNode(node.follows, item[1:]); else: return node; #遍历查看字典 def dict(self): #单词结束的末尾标记 endChar = '$'; count = 0; if (self.start != None): cursor = self.start; #具有后续节点的词段 dict_1 = []; #最终版 dict_2 = []; while cursor != None: #if (cursor.follows == None): if (cursor.follows == None): #过滤掉词尾结束标记 dict_2.append(str(cursor.item)[:-1]); else: dict_1.append(str(cursor.item)); cursor = cursor.next; while (len(dict_1) > 0): a = dict_1.pop(0); cursor = Trie.__getNode(self.start, a); count+=1; if (cursor != None): cursor = cursor.follows; while cursor != None: if (cursor.follows == None): dict_2.append((a+str(cursor.item))[:-1]); else: dict_1.append(a+str(cursor.item)); cursor = cursor.next; print('找结点{0}次'.format(count)); print('字典:', dict_2); else: print('字典为空'); </span>
用例:
<span style="font-size:18px;">def main(): #计时开始 startTime = time.clock(); t = Trie(); a = ['I', 'love', 'lot', 'lance', 'you', 'you', 'love', 'me', 'i', 'have', 'a', 'book', 'you', 'have', 'a', 'pencil', 'pen', 'paper', 'lottol', 'banana']; #插入单词,词尾加结束符 for i in range(len(a)): t.insert(a[i]+'$'); t.start.next.next.follows.next.info(); t.start.info(1); n1 = t.getNode(t.start, 'lottol'); if (n1 != None): n1.info(); n1.info(1); else: print('无该节点'); t.dict(); print('banana'+'$' in t); print('how'+'$' in t); #计时结束 endTime = time.clock(); #打印结果 print('操作用时:{0:.3e} s'.format(endTime-startTime)); </span>
短短数行代码,写得非常头痛。用递归是不是比用列表有更大好处,阿伟也不清楚。
但是有一点可以肯定,用递归可以把整个字典连成一棵树,而列表做不到。
即将奥运会了,阿伟决定好好地去研究一下奥运会,另外,最近也出了不少好看的电视剧,
也要抽点时间去看看。
本节到此结束,欲知后事如何,请看下回分解。
时间: 2024-11-08 13:29:09