π‘νΈλΌμ΄(Trie) μκ³ λ¦¬μ¦μ΄λ?
νΈλΌμ΄(Trie)
- λ¬Έμμ΄μ μ μ₯νκ³ , λΉ λ₯΄κ² νμνκΈ° μν νΈλ¦¬ ννμ μλ£κ΅¬μ‘°
- μ λμ¬λ₯Ό κΈ°μ€μΌλ‘ νμ
- λ¬Έμμ΄ λ°°μ΄μμ κ° λ¬Έμμ΄ λ³ λ¬Έμλ₯Ό μΌμΌμ΄ νμνλ κ²λ³΄λ€ νμ μλκ° λΉ λ¦
- κ° λ Έλμμ μμμ λν ν¬μΈν°λ₯Ό λ°°μ΄λ‘ μ μ₯νλ€λ μ μμ λ©λͺ¨λ¦¬λ₯Ό λ μ¬μ©
νΈλΌμ΄ ꡬ쑰
λ Έλ ꡬμ±
class Node{
//λ
Έλμ μμ λ
Έλλ€μ μ μ₯
HashMap<Character, Node> child;
//μ΄ λ
Έλκ° λ¨μ΄μ λμΈμ§ μ μ₯
boolean endOfWord;
}
λ©μλ ꡬμ±
μ½μ (insert)
“TO” μ½μ
- λ£¨νΈ λ Έλμ T μμ μμΌλ―λ‘ μμ±
- T λ Έλμ O μμ μμΌλ―λ‘ μμ±
- O λ Έλ μ΄ν λ¬Έμ λ¨μ νμ λλ¬μΌλ―λ‘ endOfWord = true μ€μ
“TA” μ½μ
- λ£¨νΈ λ Έλμ T μμ μμΌλ―λ‘ T μμμΌλ‘ μ΄λ
- T λ Έλμ A μμ μμΌλ―λ‘ μμ±
- A λ Έλ μ΄ν λ¬Έμ νμ λλ¬μΌλ―λ‘ endOfWord = true μ€μ
“CAT” μ½μ
- λ£¨νΈ λ Έλμ C μμ μμΌλ―λ‘ μμ±
- C λ Έλμ A μμ μμΌλ―λ‘ μμ±
- A λ Έλμ T μμ μμΌλ―λ‘ μμ±
- T λ Έλ μ΄ν λ¬Έμ νμ λλ¬μΌλ―λ‘ endOfWord = true μ€μ
“TREE” μ½μ
- λ£¨νΈ λ Έλμ T μμ μμΌλ―λ‘ T μμμΌλ‘ μ΄λ
- T λ Έλμ R μμ μμΌλ―λ‘ μμ±
- R λ Έλμ E μμ μμΌλ―λ‘ μμ±
- E λ Έλμ E μμ μμΌλ―λ‘ μμ±
- E λ Έλ μ΄ν λ¬Έμ νμ λλ¬μΌλ―λ‘ endOfWord = true μ€μ
νμ(search)
“TRE” νμ
- λ£¨νΈ λ Έλμ T λ Έλ μμΌλ―λ‘ μ΄λ
- T λ Έλμ R μμ μμΌλ―λ‘ μ΄λ
- R λ Έλμ E μμ μμΌλ―λ‘ μ΄λ
- E λ Έλμμ endOfWord λ false μ΄λ―λ‘ false 리ν΄
“TAKE” νμ
- λ£¨νΈ λ Έλμ T λ Έλ μμΌλ―λ‘ μ΄λ
- T λ Έλμ A μμ μμΌλ―λ‘ μ΄λ
- A λ Έλμ K μμ μμΌλ―λ‘ false 리ν΄
μμ (delete)
“TA” μμ
- “TA” νμ
- 맨 λ§μ§λ§ λ¬Έμ “A”μ endOfWordλ₯Ό false λ‘ λ³κ²½
- “A”μ μμ λ Έλκ° μλμ§ νμΈ. μμΌλ©΄ return, μμΌλ©΄ μμ ν T λ Έλλ‘ μ΄λ
- “T”μ μμ λ Έλκ° μλμ§ νμΈ. μμΌλ©΄ return, μμΌλ©΄ μμ ν λ£¨νΈ λ Έλλ‘ μ΄λ
ꡬν
Node ν΄λμ€
class Node{
//λ
Έλμ μμ λ
Έλλ€μ μ μ₯
HashMap<Character, Node> child;
//μ΄ λ
Έλκ° λ¨μ΄μ λμΈμ§ μ μ₯
boolean endOfWord;
public Node() {
this.child = new HashMap<>();
this.endOfWord = false;
}
}
Trie ν΄λμ€
public class Trie {
Node root;
public Trie(){
this.root = new Node();
}
public void insert(String str); //μ½μ
boolean search(String str); //νμ
public boolean delete(String str);//μμ
}
insert λ©μλ
public void insert(String str){
//μμ λ
Έλλ₯Ό 루νΈλ
Έλλ‘ μ€μ
Node node = this.root;
// λ¬Έμμ΄μ λ¬Έμ λ¨μλ‘ νμ
for(int i=0;i<str.length(); i++){
char c = str.charAt(i);
// ν΄λΉ λ¬Έμκ° νμ¬ λ
Έλμ μμλ
Έλ μ€μ μλμ§ νμΈ
node.child.putIfAbsent(c,new Node());
// μμΌλ©΄ μμ± ν μμλ
Έλλ‘ μ΄λ
node = node.child.get(c);
}
// λ¬Έμμ΄ νμ ν λ§μ§λ§ λ¬Έμκ° λ¨μ΄μ λμμ λͺ
μ
node.endOfWord = true;
}
search λ©μλ
public boolean search(String str){
Node node = this.root;
//λ¬Έμμ΄μ λ¬Έμ λ¨μλ‘ νμ
for(int i=0; i<str.length(); i++){
char c = str.charAt(i);
// μμ λ
Έλμ μ°Ύλ λ¬Έμκ° μμΌλ©΄ false 리ν΄
if(!node.child.containsKey(c)) return false;
// ν΄λΉ λ
Έλκ° μμΌλ©΄ μμ λ
Έλλ‘ μ΄λ
node = node.child.get(c);
}
// λ§μ§λ§ λ
Έλ λλ¬ μ, endOfWord λ°ν
return node.endOfWord;
}
delete λ©μλ
public boolean delete(String str) {
boolean result = delete(this.root, str, 0);
return result;
}
private boolean delete(Node node, String str, int idx) {
char c = str.charAt(idx);
// μ§μμΌ ν λ¬Έμκ° μμλ
Έλμ μμΌλ©΄ λ¬Έμμ΄ μμ΄μ μμ μ€ν¨, false 리ν΄
if(!node.child.containsKey(c)){
return false;
}
Node cur = node.child.get(c);
idx++;
// λ¬Έμμ΄ κΈΈμ΄ λ§νΌ νμνμ¬ λλ¬
if(idx == str.length()){
// λ¬Έμμ΄ λμ΄ endOfWord κ° μλλ©΄ λ¬Έμμ΄ μμ΄μ μμ μ€ν¨, false 리ν΄
if(!cur.endOfword){
return false;
}
// λ¬Έμμ΄ λμ endOfWordλ₯Ό falseλ‘ λ³κ²½
cur.endOfWord = false;
// μ§μ°λ €λ λ¬Έμμ΄μ λ€μ λ€λ₯Έ μμμ΄ μλ€λ©΄ νμ¬ λ
Έλμμ μμλ
Έλ μμ
// λ¬Έμμ΄ λ€μ λ€λ₯Έ μμμ΄ μλ€λ©΄ νμ λλκ³ λμκ°κΈ°
if(cur.child.isEmpty()){
node.child.remove(c);
}
}
else {
// μμ μ€ν¨
if(!this.delete(cur, str, idx)){
return false;
}
// trueλ₯Ό λ°νλ°μκ³ , νμ¬ λ
Έλμ μμλ
Έλκ° λΉμ΄μμΌλ©΄ νμ¬ λ
Έλλ₯Ό λΆλͺ¨μ μμμμ μμ
if(!cur.endOfWord && cur.child.isEmpty()){
node.child.remove(c);
}
}
return true;
}
μ 체 μ½λ
λ보기
class Node{
//λ
Έλμ μμ λ
Έλλ€μ μ μ₯
HashMap<Character, Node> child;
//μ΄ λ
Έλκ° λ¨μ΄μ λμΈμ§ μ μ₯
boolean endOfWord;
public Node() {
this.child = new HashMap<>();
this.endOfWord = false;
}
}
public class Trie {
Node root;
public Trie(){
this.root = new Node();
}
public void insert(String str){
//μμ λ
Έλλ₯Ό 루νΈλ
Έλλ‘ μ€μ
Node node = this.root;
// λ¬Έμμ΄μ λ¬Έμ λ¨μλ‘ νμ
for(int i=0;i<str.length(); i++){
char c = str.charAt(i);
// ν΄λΉ λ¬Έμκ° νμ¬ λ
Έλμ μμλ
Έλ μ€μ μλμ§ νμΈ
node.child.putIfAbsent(c,new Node());
// μμΌλ©΄ μμ± ν μμλ
Έλλ‘ μ΄λ
node = node.child.get(c);
}
// λ¬Έμμ΄ νμ ν λ§μ§λ§ λ¬Έμκ° λ¨μ΄μ λμμ λͺ
μ
node.endOfWord = true;
}
public boolean search(String str){
Node node = this.root;
//λ¬Έμμ΄μ λ¬Έμ λ¨μλ‘ νμ
for(int i=0; i<str.length(); i++){
char c = str.charAt(i);
// μμ λ
Έλμ μ°Ύλ λ¬Έμκ° μμΌλ©΄ false 리ν΄
if(!node.child.containsKey(c)) return false;
// ν΄λΉ λ
Έλκ° μμΌλ©΄ μμ λ
Έλλ‘ μ΄λ
node = node.child.get(c);
}
// λ§μ§λ§ λ
Έλ λλ¬ μ, endOfWord λ°ν
return node.endOfWord;
}
public boolean delete(String str) {
boolean result = delete(this.root, str, 0);
return result;
}
private boolean delete(Node node, String str, int idx) {
char c = str.charAt(idx);
// μ§μμΌ ν λ¬Έμκ° μμλ
Έλμ μμΌλ©΄ λ¬Έμμ΄ μμ΄μ μμ μ€ν¨, false 리ν΄
if(!node.child.containsKey(c)){
return false;
}
Node cur = node.child.get(c);
idx++;
// λ¬Έμμ΄ κΈΈμ΄ λ§νΌ νμνμ¬ λλ¬
if(idx == str.length()){
// λ¬Έμμ΄ λμ΄ endOfWord κ° μλλ©΄ λ¬Έμμ΄ μμ΄μ μμ μ€ν¨, false 리ν΄
if(!cur.endOfword){
return false;
}
// λ¬Έμμ΄ λμ endOfWordλ₯Ό falseλ‘ λ³κ²½
cur.endOfWord = false;
// μ§μ°λ €λ λ¬Έμμ΄μ λ€μ λ€λ₯Έ μμμ΄ μλ€λ©΄ νμ¬ λ
Έλμμ μμλ
Έλ μμ
// λ¬Έμμ΄ λ€μ λ€λ₯Έ μμμ΄ μλ€λ©΄ νμ λλκ³ λμκ°κΈ°
if(cur.child.isEmpty()){
node.child.remove(c);
}
}
else {
// μμ μ€ν¨
if(!this.delete(cur, str, idx)){
return false;
}
// trueλ₯Ό λ°νλ°μκ³ , νμ¬ λ
Έλμ μμλ
Έλκ° λΉμ΄μμΌλ©΄ νμ¬ λ
Έλλ₯Ό λΆλͺ¨μ μμμμ μμ
if(!cur.endOfWord && cur.child.isEmpty()){
node.child.remove(c);
}
}
return true;
}
}