[자료구조] 08. Trie(트라이)를 사용하여 검색 자동완성 기능을 구현해 본다.
Trie 란?
그림과 같이 트리구조를 가지며 문자열을 효율적으로 검색하고 저장하기위해 단어의 글자를 노드로 이어져있으며 단어의 끝에는 끝을 확인 할 수 있는 확인자가 있는 구조이다.
자동완성에서 Trie를 쓰는 이유?
String 구조를 트리에 담아 검색한다고 가정해보자
트리의 대표적인 구조인 이진탐색트리와 비교해보면 String의 길이를 M이라고 했을때, 시간복잡도는 O(M*log(N)) 이고
Trie의 경우 시간복잡도는 O(M)이 된다. 즉, 시간복잡도면에서 우월한 성능을 보이기 때문에 자동완성에서 Trie를 사용한다고 볼 수 있다.
구현 코드
1. 메인 코드
# 노드 설정
class Node():
def __init__(self, value):
self.value = value
self.fin = False # 단어가 끝났을 경우 해당 단어를 집어넣는다.
self.next = dict()
# 트라이 설정
class Trie():
def __init__(self):
self.head = Node(None)
# 단어 삽입
def insert(self, string):
curr_node = self.head
for word in string:
if word not in curr_node.next:
curr_node.next[word] = Node(word)
curr_node = curr_node.next[word]
curr_node.fin = string
# 자동완성
def auto_complete(self, string):
curr_node = self.head
result = []
for word in string:
if word not in curr_node.next:
return "추천 검색어가 없습니다."
else:
curr_node = curr_node.next[word]
if curr_node.fin:
result.append(curr_node.fin)
stack = list(curr_node.next.values())
while stack:
v = stack.pop()
if v.fin:
result.append(v.fin)
stack.extend(list(v.next.values()))
return print(result)
# 검색기록 출력
def show_list(self):
curr_node = self.head
stack = list(curr_node.next.values())
result = []
while stack:
v = stack.pop()
if v.fin:
result.append(v.fin)
stack.extend(list(v.next.values()))
return print(result)
2. 결과
# 초기화
T = Trie()
# 단어 삽입
T.insert('string')
T.insert('str')
T.insert('stress')
T.insert('star')
T.insert('singer')
T.insert('sign')
T.insert('starcraft')
T.insert('southkorea')
T.insert('south korea')
# 자동완성 기능
T.auto_complete('soo')
T.auto_complete('st')
T.auto_complete('star')
T.auto_complete('south')
# 검색기록 출력
T.show_list()
# Result
# 자동완성
'추천 검색어가 없습니다.'
['star', 'starcraft', 'str', 'stress', 'string']
['star', 'starcraft']
['south korea', 'southkorea']
# 검색기록
['south korea', 'southkorea', 'sign', 'singer', 'star', 'starcraft', 'str', 'stress', 'string']