[알고리즘] 파이썬으로 Trie 구현하기(2)
1편에 이어 2편이다. 지난 장에서는 trie의 간단한 개념과 생성과 입력 기능에 대해 알아보았다. 이번 편에서는 조회와 삭제에 대해 알아보도록 하겠다.
조회 부분의 원리는 간단하다. 입력한 접두어가 저장되어 있는지 확인하고 해당 접두어가 있다면 그 접두어를 포함하고 있는 모든 단어를 반환해주는 함수이다.
여기서 queue 부분이 이해가 안갈수도 있을것 같다. 일단 queue 부분은 items()를 이용해 dict의 key, value 값, 즉 노드의 정보를 list에 담아오는 코드이다. 즉, 검색어로 입력한 단어를 포함하는 모든 단어를 찾기위해 검색어로 입력한 이후부분에 해당하는 모든 노드를 찾기 위해 노드 정보를 가져오는 것이다. 그 다음 queue.pop()을 이용해 리스트에 담겨져있는 노드정보를 꺼내 current_node에 저장하고 current_node에 데이터가 있으면 words라는 리스트에 붙이는 과정이라고 이해하면 된다.
그 다음은 삭제이다. 삭제는 삭제하고자 하는 단어를 입력하면 그 단어가 있는지 확인하고 공통 접두어가 있는 부분까지 삭제하는 방식이다. 이때 NodeCount가 사용이 되는데 NodeCount가 2 이상이면 자식 노드가 2개 이상이라는 뜻이기 때문에 그 노드에서 삭제를 멈추게하는 방식이다. 하지만 이 삭제 함수의 문제가 하나 있는데 stand와 standard를 구분하지 못한다는 것이다. standard를 삭제하면 stand는 남아있지만, stand를 삭제하면 standard도 삭제한다는 단점이 있다. 이 부분은 차후에 수정을...
접두어로 검색
Trie의 가장 큰 장점이라고 생각하는 접두어 검색 기능이다. 단어의 일부분으로 전체단어를 검색할 수 있다. 예를들어 trie에 gold, good, gerald를 저장한 다음 검색어에 g를 입력하면 gold, good, gerald를 모두 검색할 수 있다. 이런 기능은 검색어 자동완성에 쓰인다고 한다.
우선 검색 부분의 코드를 보도록 하겠다.
우선 검색 부분의 코드를 보도록 하겠다.
def search_with_prefix(self, prefix):
words = list()
if prefix is None:
raise ValueError('Requires not-Null prefix')
top_node = self.head
for letter in prefix:
if letter in top_node.children:
top_node = top_node.children[letter]
else:
return words
if top_node == self.head:
queue = [node for key, node in top_node.children.items()]
else:
queue = [top_node]
while queue:
current_node = queue.pop()
if current_node.data is not None:
words.append(current_node.data)
queue = [node for key, node in current_node.children.items()] + queue
return words
조회 부분의 원리는 간단하다. 입력한 접두어가 저장되어 있는지 확인하고 해당 접두어가 있다면 그 접두어를 포함하고 있는 모든 단어를 반환해주는 함수이다.
여기서 queue 부분이 이해가 안갈수도 있을것 같다. 일단 queue 부분은 items()를 이용해 dict의 key, value 값, 즉 노드의 정보를 list에 담아오는 코드이다. 즉, 검색어로 입력한 단어를 포함하는 모든 단어를 찾기위해 검색어로 입력한 이후부분에 해당하는 모든 노드를 찾기 위해 노드 정보를 가져오는 것이다. 그 다음 queue.pop()을 이용해 리스트에 담겨져있는 노드정보를 꺼내 current_node에 저장하고 current_node에 데이터가 있으면 words라는 리스트에 붙이는 과정이라고 이해하면 된다.
삭제
def delete_word(self, word, depth=0):
current_node = self.head
for letter in word[:-1]:
if letter not in current_node.children:
return False
current_node = current_node.children[letter]
if current_node.NodeCount > 1:
del current_node.children[word[-1]]
return True
if word[-1] in current_node.children:
del current_node.children[word[-1]]
self.delete_word(word[:-1], depth)
return True
return False
그 다음은 삭제이다. 삭제는 삭제하고자 하는 단어를 입력하면 그 단어가 있는지 확인하고 공통 접두어가 있는 부분까지 삭제하는 방식이다. 이때 NodeCount가 사용이 되는데 NodeCount가 2 이상이면 자식 노드가 2개 이상이라는 뜻이기 때문에 그 노드에서 삭제를 멈추게하는 방식이다. 하지만 이 삭제 함수의 문제가 하나 있는데 stand와 standard를 구분하지 못한다는 것이다. standard를 삭제하면 stand는 남아있지만, stand를 삭제하면 standard도 삭제한다는 단점이 있다. 이 부분은 차후에 수정을...
if __name__ == '__main__':
trie = Trie()
trie.insert_word('good gerald gold')
print(trie.search_with_prefix('g'))
trie.delete_word('gold')
print(trie.search_with_prefix('g'))
댓글
댓글 쓰기