Trie ์๋ฃ๊ตฌ์กฐ๋ ๋ฌธ์์ด์ ํจ์จ์ ์ผ๋ก ์ ์ฅํ๊ณ ๊ฒ์ํ๊ธฐ ์ํด ์ค๊ณ๋ ํธ๋ฆฌ ๊ธฐ๋ฐ์ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
์ฃผ๋ก ๋ฌธ์์ด ๊ฒ์, ์๋ ์์ฑ, ์ฌ์ ๊ตฌํ ๋ฑ ๋ค์ํ ์์ฉ ํ๋ก๊ทธ๋จ์์ ์ฌ์ฉ๋๋ค.
๋ฐ์์ด ์ฒ์์๋ 'ํธ๋ฆฌ'์์ง๋ง, ํธ๋ฆฌ(Tree) ์๋ฃ๊ตฌ์กฐ์ ๊ตฌ๋ถํ๊ธฐ ์ํด 'ํธ๋ผ์ด'๋ก ๋ฐ๋์๋ค๊ณ ํ๋ค.
์ํ๋ ์์๋ฅผ ์ฐพ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ด์ง ๊ฒ์ ํธ๋ฆฌ์์๋ ์์๋ฅผ ์ฐพ๋ ๋ฐ ์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค.
ํ์ง๋ง ๋ฌธ์์ด์ ๊ฒฝ์ฐ ๋ ๋ฌธ์์ด์ ๋น๊ตํ๊ธฐ ์ํด์๋ ๋ฌธ์์ด์ ๊ธธ์ด ๋งํผ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์, ์ํ๋ ๋ฌธ์์ด์ ์ฐพ๊ธฐ ์ํด์๋ ์ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค.
์ด๋ฌํ ๋จ์ ์ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฌธ์์ด ํนํ ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ฐ๋ก ์ด ํธ๋ผ์ด(Trie)์ด๋ค.
๋ค์ ๊ทธ๋ฆผ์ ๋ฌธ์์ด ์งํฉ {"apple", "april", "busy", "beer", "best"}
๋ฅผ ํธ๋ผ์ด๋ก ๊ตฌํํ ๊ฒ์ด๋ค.
ํธ๋ผ์ด๋ ํ ๋ฌธ์์ด์์ ๋ค์์ ๋์ค๋ ๋ฌธ์๊ฐ ํ์ฌ ๋ฌธ์์ ์์ ๋ ธ๋๊ฐ ๋๊ณ , ํ๋์์ผ๋ก ๋ํ๋ธ ๋ฆฌํ ๋ ธ๋๋ ๋ฌธ์์ด์ ๋์ ์๋ฏธํ๋ค.
ํธ๋ผ์ด๋ ๋ฌธ์์ด์ ํ์ํ๊ธฐ ์ํ ์๋ฃ๊ตฌ์กฐ์ด๋ฏ๋ก ๋ฌธ์์ด ํ์์ ์ํด์๋ ๋ค์ ๊ธ์์ ํด๋นํ๋ ๋ ธ๋๋ฅผ ํ๊ณ ๋ฐ๋ผ๊ฐ๋ฉด ๋๋ค.
์๋ฅผ ๋ค์ด "april"
์ ์ฐพ๋๋ค๊ณ ๊ฐ์ ํด๋ณด์.
a โ ap โ apr โ apri โ april
์ ์์๋ก ํ์๋๋ฏ๋ก "april"
์ ๋ชจ๋ ์ ๋์ฌ๋ค์ด ๋ค ๊ตฌํด์ง๊ฒ ๋๋ค.
์๋ฐ๋ก Trie
๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์๋ ์๋ฃ๊ตฌ์กฐ์ธ Trie
์ ์ด๋ฅผ ๊ตฌ์ฑํ TrieNode
ํด๋์ค๊ฐ ๊ฐ๊ฐ ํ์ํ๋ค.
TrieNode
๋ ์์ ๋
ธ๋ Map๊ณผ ํ์ฌ ๋
ธ๋๊ฐ ๋ง์ง๋ง ๊ธ์์ธ์ง ์ฌ๋ถ์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
public class TrieNode {
// ์์ ๋
ธ๋ Map
private Map<Character, TrieNode> childNodes = new HashMap<>();
// ๋ง์ง๋ง ๊ธ์์ธ์ง ์ฌ๋ถ
private boolean isLastChar;
}
์ด๋ ๊ฒ ๋ ๋ณ์๊ฐ ํ ๋น๋์์ผ๋ ์ด ๋ณ์์ ์ ๊ทผํ ์ ์๋ Getter์ Setter๊ฐ ํ์ํ๋ค.
childNodes
๋ Trie์ฐจ์์์ ์์ฑํด ์ฝ์
ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, Getter๋ง ์์ฑํด ์ค๋ค.
isLastChar
๋ ์ถํ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๊ณผ์ ์์ ๋ณ๊ฒฝ์ด ํ์ํ๊ธฐ ๋๋ฌธ์, Getter์ Setter๋ฅผ ๋ ๋ค ์์ฑํด ์ค๋ค.
public class TrieNode {
// ์์ ๋
ธ๋ Map
private Map<Character, TrieNode> childNodes = new HashMap<>();
// ๋ง์ง๋ง ๊ธ์์ธ์ง ์ฌ๋ถ
private boolean isLastChar;
// ์์ ๋
ธ๋ ๋งต Getter
Map<Character, TrieNode> getChildNodes() {
return this.childNodes;
}
// ๋ง์ง๋ง ๊ธ์์ธ์ง ์ฌ๋ถ Getter
boolean isLastChar() {
return this.isLastChar;
}
// ๋ง์ง๋ง ๊ธ์์ธ์ง ์ฌ๋ถ Setter
void setIsLastChar(boolean isLastChar) {
this.isLastChar = isLastChar;
}
}
Trie
๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋น ๋ฌธ์์ด์ ๊ฐ์ง๋ ๋ฃจํธ ๋
ธ๋๋ง ๊ฐ์ง๊ณ ์๋ค.
public class Trie {
private TrieNode rootNode; // ๋ฃจํธ ๋
ธ๋
}
์์ ๋
ธ๋๋ ๊ณง ๋์ฌ insert
๋ฉ์๋๋ฅผ ํตํด ๋ฌธ์๋ฅผ ์
๋ ฅํจ์ผ๋ก์จ ์์ฑ๋ ๊ฒ์ด๋ค.
์ฐ์ , Trie
๊ฐ ์์ฑ๋๋ฉด rootNode
๊ฐ ์์ฑ๋ ์ ์๋๋ก ์์ฑ์๋ฅผ ํตํด rootNode
๋ฅผ ์์ฑํด ์ค๋ค.
public class Trie {
private TrieNode rootNode; // ๋ฃจํธ ๋
ธ๋
// ์์ฑ์
Trie() {
rootNode = new TrieNode();
}
}
insert ๋ฉ์๋์์๋ ์
๋ ฅ๋ฐ์ ๋จ์ด์ ๊ฐ ์ํ๋ฒณ์ ๊ณ์ธต ๊ตฌ์กฐ์ ์์ ๋
ธ๋๋ก ๋ง๋ค์ด ๋ฃ๋ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
์ด ๋, ์ด๋ฏธ ๊ฐ์ ์ํ๋ฒณ์ด ์กด์ฌํ๋ฉด ๊ณตํต ์ ๋์ด ๋ถ๋ถ๊น์ง๋ ์์ฑํ์ง ์๋๋ค.
์ฆ, ํด๋น ๊ณ์ธต ๋ฌธ์์ ์์ ๋
ธ๋๊ฐ ์กด์ฌํ์ง ์์ ๋๋ง ์์ ๋
ธ๋๋ฅผ ์์ฑํด์ค๋ค.
์๋ฅผ ๋ค์ด, "apple"
์ด ๋ค์ด์๋ Trie
์ "april"
์ ๋ฃ์ ๋, "ap"
๋ ์ค๋ณต์ด๋ฏ๋ก "a โ p"
๋
ธ๋ ์๋ "โ r โ i โ l"
๋ง ์ถ๊ฐ๋ก ์์ ๋
ธ๋๋ฅผ ์์ฑํด ์ฃผ๋ฉด ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฆฌํ ๋
ธ๋์์๋ ๋ง์ง๋ง ๋ฌธ์๋ผ๋ ๊ฒ์ ํ์ํ๊ธฐ ์ํด setIsLastChar(true)
๋ฅผ ํด์ค๋ค.
void insert(String word) {
TrieNode thisNode = this.rootNode;
for (int i = 0; i < word.length(); i++) {
thisNode = thisNode.getChildNodes().computeIfAbsent(word.charAt(i), c -> new TrieNode());
}
thisNode.setIsLastChar(true);
}
ํน์ ๋จ์ด๊ฐ Trie
์ ์กด์ฌํ๋ ์ง ํ์ธํ๊ธฐ ์ํด์๋ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑ์์ผ์ผ ํ๋ค.
๋ฃจํธ ๋ ธ๋๋ถํฐ ์์๋๋ก ์ํ๋ฒณ์ด ์ผ์นํ๋ ์์ ๋ ธ๋๋ค์ด ์กด์ฌํ ๊ฒ
ํด๋น ๋จ์ด์ ๋ง์ง๋ง ๊ธ์์ ํด๋นํ๋ ๋
ธ๋์ isLastChar
๊ฐ true์ผ ๊ฒ
boolean contains(String word) {
TrieNode thisNode = this.rootNode;
for (int i = 0; i < word.length(); i++) {
char character = word.charAt(i);
TrieNode node = thisNode.getChildNodes().get(character);
if (node == null)
return false;
thisNode = node;
}
return thisNode.isLastChar();
}
๋ง์ง๋ง์ผ๋ก ๋จ์ด๋ฅผ ์ญ์ ํ๋ ๋ฉ์๋์ด๋ค.
์ผ๋จ, contains ๋ฉ์๋์ฒ๋ผ ์ฃผ์ด์ง ๋จ์ด๋ฅผ ์ฐพ์ ํ์ ๋
ธ๋๋ก ๋จ์ด ๊ธธ์ด๋งํผ ๋ด๋ ค๊ฐ๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ ๋
ธ๋๋ค์ด ๋ถ๋ชจ ๋
ธ๋์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์, ํ์ ๋
ธ๋๋ก ๋ด๋ ค๊ฐ๋ฉฐ ์ญ์ ๋์ ๋จ์ด๋ฅผ ํ์ํ๊ณ , ๋ค์ ์ฌ๋ผ์ค๋ฉฐ ์ญ์ ํ๋ ๊ณผ์ ์ด ๊ตฌํ๋์ด์ผ ํ๋ค๋ ์ ์ด๋ค.
delete ๋ฉ์๋๋ ์๋์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํ๋ค.
isLastChar
์ด true
์ฌ์ผ ํ๋ค.isLastChar
์ด false
์ฌ์ผ ํ๋ค.void delete(String word) {
delete(this.rootNode, word, 0);
}
private void delete(TrieNode thisNode, String word, int index) {
char character = word.charAt(index);
TrieNode childNode = thisNode.getChildNodes().get(character);
index++;
if(index == word.length()) {
childNode.setIsLastChar(false);
// ์ญ์ ๋์ ์ธ์ด์ ์ ์ผ ๋์ผ๋ก์จ ์์ ๋
ธ๋๊ฐ ์์ผ๋ฉด(์ด ๋จ์ด๋ฅผ ํฌํจํ๋ ๋ ๊ธด ๋จ์ด๊ฐ ์์ผ๋ฉด) ์ญ์ ์์
if (childNode.getChildNodes().isEmpty())
thisNode.getChildNodes().remove(character);
}
else {
delete(childNode, word, index);
// ์ญ์ ์ค, ์์ ๋
ธ๋๊ฐ ์๊ณ ํ์ฌ ๋
ธ๋๋ก ๋๋๋ ๋ค๋ฅธ ๋จ์ด๊ฐ ์๋ ๊ฒฝ์ฐ ์ด ๋
ธ๋ ์ญ์
if(!childNode.isLastChar() && childNode.getChildNodes().isEmpty())
thisNode.getChildNodes().remove(character);
}
}
๐ปReference
[JAVA/์๋ฃ๊ตฌ์กฐ] ํธ๋ผ์ด(Trie) ๊ฐ๋
, ์ง์ ๊ตฌํํ๊ธฐ
์ด๋ ต๊ตฌ๋จผ...๊ทธ๋๋ ํธ๋ผ์ดํด๋ณด์๊ณ ~!๐ฅ๐ฅ๐๐