logo

트라이 데이터 구조 | 삽입 및 검색

그만큼 트라이 데이터 구조 동적 문자열 세트를 저장하는 데 사용되는 트리형 데이터 구조입니다. 일반적으로 효율적인 용도로 사용됩니다. 검색 그리고 저장 대규모 데이터 세트의 키 수입니다. 구조는 다음과 같은 작업을 지원합니다. 삽입 , 찾다 , 그리고 삭제 키를 사용하여 컴퓨터 과학 및 정보 검색과 같은 분야에서 귀중한 도구가 됩니다. 이 기사에서 우리는 탐구 할 것입니다 삽입 및 검색 Trie 데이터 구조에서의 연산.

트라이 데이터 구조

트라이 데이터 구조



내용의 테이블

  • Trie Node의 표현
  • Trie 노드의 표현:

    트라이 데이터 구조 Edge로 연결된 노드로 구성됩니다. 각 노드는 문자 또는 문자열의 일부를 나타냅니다. Trie의 시작점인 루트 노드는 빈 문자열을 나타냅니다. 노드에서 나오는 각 가장자리는 특정 문자를 나타냅니다. 루트에서 노드까지의 경로는 Trie에 저장된 문자열의 접두사를 나타냅니다.

    영어 알파벳의 노드를 표현하는 간단한 구조는 다음과 같다.



    CSS 코멘트
    C++
    struct TrieNode {  // pointer array for child nodes of each node  TrieNode* childNode[26];  // Used for indicating ending of string  bool wordEnd;  TrieNode()  {  // constructor  // initialize the wordEnd variable with false  // initialize every index of childNode array with  // NULL  wordEnd = false;  for (int i = 0; i < 26; i++) {  childNode[i] = NULL;  }  } };>
    자바
    public class TrieNode {    // Array for child nodes of each node  TrieNode[] childNode;    // Used for indicating the end of a string  boolean wordEnd;  // Constructor  public TrieNode() {  // Initialize the wordEnd variable with false  wordEnd = false;  // Initialize every index of the childNode array with null  childNode = new TrieNode[26];  for (int i = 0; i < 26; i++) {  childNode[i] = null;  }  } }>

    Trie 데이터 구조에 단어를 삽입하는 과정을 살펴보겠습니다. 우리는 이미 Trie와 해당 노드 구조의 기본 사항을 다루었습니다.

    bash if 문

    다음은 단어 삽입을 시각적으로 표현한 것입니다. 그리고 그리고 ~에 Trie 데이터 구조로:


    Trie 데이터 구조에 삽입 작업


    Trie 데이터 구조에 삽입 및 삽입:

    • 루트 노드에서 시작합니다. 루트 노드에는 연관된 문자가 없으며 해당 노드는 단어 끝 가치는 0 , 이 시점에서 완전한 단어가 끝나지 않음을 나타냅니다.
    • 첫 번째 문자 a: '를 사용하여 지수를 계산합니다. a' – 'a' = 0 . 다음과 같은지 확인하세요. 자식노드[0] ~이다 없는 . 그렇기 때문에 해당 캐릭터로 새로운 TrieNode를 생성합니다. , 단어 끝 로 설정 0 , 그리고 빈 포인터 배열. 이 새 노드로 이동합니다.
    • 두 번째 문자 n: 다음을 사용하여 지수를 계산합니다. 'n' – 'a' = 13 . 다음 사항을 확인하세요. 자식노드[13] ~이다 없는 . 그렇다면 해당 캐릭터로 새로운 TrieNode를 생성하세요. N , 단어 끝 로 설정 0 , 그리고 빈 포인터 배열. 이 새 노드로 이동합니다.
    • 세 번째 문자 d: '를 사용하여 지수를 계산합니다. d' – 'a' = 3 . 다음 사항을 확인하세요. 자식노드[3 ] 이다 없는 . 그렇다면 해당 캐릭터로 새로운 TrieNode를 생성하세요. , 단어 끝 로 설정 1 (단어를 나타내는 그리고 여기서 끝).

    Trie 데이터 구조에 개미 삽입:

    자바 int를 문자열로
    • 루트 노드에서 시작합니다. 루트 노드에는 데이터가 포함되어 있지 않지만 삽입된 모든 문자열의 모든 첫 번째 문자를 추적합니다.
    • 첫 번째 문자 a: '를 사용하여 지수를 계산합니다. a' – 'a' = 0 . 다음과 같은지 확인하세요. 자식노드[0] ~이다 없는 . 우리는 이미 이전 삽입에서 생성된 노드입니다. 그래서 기존으로 이동 마디.
    • 첫 번째 문자 n: '를 사용하여 지수를 계산합니다. n' – 'a' = 13 . 다음 사항을 확인하세요. 자식노드 [13]은 없는 . 그렇지 않으니 기존으로 넘어가세요 N 마디.
    • 두 번째 문자 t: 다음을 사용하여 지수를 계산합니다. 't' - 'a' = 19 . 다음 사항을 확인하세요. 자식노드 [19]는 없는 . 그렇다면 해당 캐릭터로 새로운 TrieNode를 생성하세요. , 단어 끝 로 설정 1 (개미라는 단어가 여기서 끝나는 것을 나타냄)

    다음은 Trie 데이터 구조에 문자열 삽입을 구현한 것입니다.

    C++
    #include  using namespace std; struct TrieNode {  // pointer array for child nodes of each node  TrieNode* childNode[26];  // Used for indicating ending of string  bool wordEnd;  TrieNode()  {  // constructor  // initialize the wordEnd variable with false  // initialize every index of childNode array with  // NULL  wordEnd = false;  for (int i = 0; i < 26; i++) {  childNode[i] = NULL;  }  } }; void insert_key(TrieNode* root, string& key) {  // Initialize the currentNode pointer  // with the root node  TrieNode* currentNode = root;  // Iterate across the length of the string  for (auto c : key) {  // Check if the node exist for the current  // character in the Trie.  if (currentNode->childNode[c - 'a'] == NULL) { // 현재 캐릭터에 대한 노드가 존재하지 않으면 // 새 노드를 만듭니다. TrieNode* newNode = new TrieNode();  // 새로 생성된 노드에 대한 참조를 // 유지합니다.  currentNode->childNode[c - 'a'] = newNode;  } // 이제 현재 노드 포인터를 새로 생성된 노드로 // 이동합니다.  currentNode = currentNode->childNode[c - 'a'];  } // 마지막 currentNode 포인터에 대해 // wordEndCount를 증가시킵니다. 이는 // currentNode로 끝나는 문자열이 있음을 의미합니다.  currentNode->wordEnd = 1; }>

    시간 복잡도: O(단어 수 * maxLengthOfWord)
    보조 공간: O(단어 수 * maxLengthOfWord)

    Trie 데이터 구조에서 키를 검색하는 것은 삽입 작업과 유사합니다. 그러나 그것은 단지 문자를 비교하고 아래로 이동합니다. . 문자열이 끝나거나 트리에 키가 없으면 검색이 종료될 수 있습니다.

    Trie 데이터 구조 검색을 위한 단계별 접근 방식:

    리눅스 폴더 이름 바꾸기
    • 루트 노드에서 시작합니다. 이는 Trie 내의 모든 검색의 시작점입니다.
    • 검색하려는 단어의 문자를 기반으로 Trie를 탐색하세요. 각 캐릭터에 대해 Trie의 해당 분기를 따르십시오. 분기가 존재하지 않으면 해당 단어가 Trie에 존재하지 않습니다.
    • 단어 끝에 도달하고 wordEnd 플래그가 1로 설정되면 해당 단어를 찾은 것입니다.
    • 단어 끝에 도달하고 wordEnd 플래그가 0인 경우 해당 단어는 기존 단어와 접두사를 공유하더라도 Trie에 존재하지 않습니다.

    다음은 검색어를 시각적으로 표현한 것입니다. 아빠 Trie 데이터 구조에서:

    단어를 성공적으로 삽입했다고 가정해 보겠습니다. 그리고 , ~에 , 그리고 아빠 Trie 데이터 구조 내에서 특정 단어를 검색해야 합니다. 단어를 검색해 보겠습니다. 아빠 :


    Trie 데이터 구조의 검색 작업


    • 루트 노드에서 시작합니다.
    • 문자 'd'에 해당하는 분기를 따릅니다.
    • 문자 a'에 해당하는 가지를 따릅니다.
    • 문자 'd'에 해당하는 분기를 따릅니다.
    • 우리는 단어의 끝에 도달하고 단어 끝 플래그는 1 . 이는 다음을 의미합니다. 아빠 Trie에 존재합니다.

    다음은 Trie 데이터 구조에서 문자열 검색을 구현한 것입니다.

    C++
    #include  using namespace std; struct TrieNode {  // pointer array for child nodes of each node  TrieNode* childNode[26];  // Used for indicating ending of string  bool wordEnd;  TrieNode()  {  // constructor  // initialize the wordEnd variable with false  // initialize every index of childNode array with  // NULL  wordEnd = false;  for (int i = 0; i < 26; i++) {  childNode[i] = NULL;  }  } }; bool search_key(TrieNode* root, string& key) {  // Initialize the currentNode pointer  // with the root node  TrieNode* currentNode = root;  // Iterate across the length of the string  for (auto c : key) {  // Check if the node exist for the current  // character in the Trie.  if (currentNode->childNode[c - 'a'] == NULL) { // 주어진 단어가 Trie에 존재하지 않습니다. return false;  } // currentNode 포인터를 // 현재 문자에 ​​대한 기존 노드로 이동합니다.  currentNode = currentNode->childNode[c - 'a'];  } return (currentNode->wordEnd == true); }>

    시간 복잡도: O(단어 수 * maxLengthOfWord)
    보조 공간: O(단어 수 * maxLengthOfWord)

    문자열 정수

    다음을 사용하여 루트 노드를 만듭니다. 트라이노드() 건설자.

  • 트라이에 삽입되어야 하는 문자열 모음을 문자열 벡터에 저장합니다. 도착 .
  • Trie에 모든 문자열 삽입 의 도움으로 insert_key() 기능,
  • 다음의 도움으로 문자열 검색 검색_키() 기능.

다음은 위의 접근 방식을 구현한 것입니다.

C++
#include  using namespace std; struct TrieNode {  // pointer array for child nodes of each node  TrieNode* childNode[26];  // Used for indicating ending of string  bool wordEnd;  TrieNode()  {  // constructor  // initialize the wordEnd variable with false  // initialize every index of childNode array with  // NULL  wordEnd = false;  for (int i = 0; i < 26; i++) {  childNode[i] = NULL;  }  } }; void insert_key(TrieNode* root, string& key) {  // Initialize the currentNode pointer  // with the root node  TrieNode* currentNode = root;  // Iterate across the length of the string  for (auto c : key) {  // Check if the node exist for the current  // character in the Trie.  if (currentNode->childNode[c - 'a'] == NULL) { // 현재 캐릭터에 대한 노드가 존재하지 않으면 // 새 노드를 만듭니다. TrieNode* newNode = new TrieNode();  // 새로 생성된 노드에 대한 참조를 // 유지합니다.  currentNode->childNode[c - 'a'] = newNode;  } // 이제 현재 노드 포인터를 새로 생성된 노드로 // 이동합니다.  currentNode = currentNode->childNode[c - 'a'];  } // 마지막 currentNode 포인터에 대한 wordEndCount를 증가시킵니다. // 이는 currentNode로 끝나는 문자열이 있음을 의미합니다.  currentNode->wordEnd = 1; } bool search_key(TrieNode* root, string& key) { // 루트 노드로 // currentNode 포인터를 초기화 TrieNode* currentNode = root;  // 문자열 길이를 반복합니다. for (auto c : key) { // Trie의 현재 문자에 ​​대한 노드가 // 존재하는지 확인합니다.  if (currentNode->childNode[c - 'a'] == NULL) { // 주어진 단어가 Trie에 존재하지 않습니다. return false;  } // currentNode 포인터를 // 현재 문자에 ​​대한 기존 노드로 이동합니다.  currentNode = currentNode->childNode[c - 'a'];  } return (currentNode->wordEnd == true); } // 드라이버 코드 int main() { // Trie에 대한 루트 노드 만들기 TrieNode* root = new TrieNode();  // Trie 벡터에 삽입하려는 문자열을 // 저장합니다.inputStrings = { 'and', 'ant', 'do', 'geek', 'dad', 'ball' };  // Trie의 삽입 작업 수 int n = inputStrings.size();  for (int i = 0; i< n; i++) {  insert_key(root, inputStrings[i]);  }  // Stores the strings that we want to search in the Trie  vectorsearchQueryStrings = { 'do', 'geek', 'bat' };  // Trie의 검색 작업 수 int searchQueries = searchQueryStrings.size();  for (int i = 0; i< searchQueries; i++) {  cout << 'Query String: ' << searchQueryStrings[i]  << '
';  if (search_key(root, searchQueryStrings[i])) {  // the queryString is present in the Trie  cout << 'The query string is present in the '  'Trie
';  }  else {  // the queryString is not present in the Trie  cout << 'The query string is not present in '  'the Trie
';  }  }  return 0; }>
자바
class TrieNode {  TrieNode[] childNode;  boolean wordEnd;  TrieNode()  {  childNode = new TrieNode[26];  wordEnd = false;  } } class Trie {  TrieNode root;  Trie() { root = new TrieNode(); }  // Function to insert a key into the Trie  void insert(String key)  {  TrieNode currentNode = root;  for (int i = 0; i < key.length(); i++) {  int index = key.charAt(i) - 'a';  if (currentNode.childNode[index] == null) {  currentNode.childNode[index]  = new TrieNode();  }  currentNode = currentNode.childNode[index];  }  currentNode.wordEnd = true;  }  // Function to search for a key in the Trie  boolean search(String key)  {  TrieNode currentNode = root;  for (int i = 0; i < key.length(); i++) {  int index = key.charAt(i) - 'a';  if (currentNode.childNode[index] == null) {  return false;  }  currentNode = currentNode.childNode[index];  }  return currentNode.wordEnd;  } } public class Main {  public static void main(String[] args)  {  Trie trie = new Trie();  String[] inputStrings  = { 'and', 'ant', 'do', 'geek', 'dad', 'ball' };  // Insert each string into the Trie  for (String str : inputStrings) {  trie.insert(str);  }  String[] searchQueryStrings  = { 'do', 'geek', 'bat' };  // Search for each string and print whether it is  // found in the Trie  for (String query : searchQueryStrings) {  System.out.println('Query String: ' + query);  if (trie.search(query)) {  System.out.println(  'The query string is present in the Trie');  }  else {  System.out.println(  'The query string is not present in the Trie');  }  }  } }>
파이썬
class TrieNode: def __init__(self): self.childNode = [None] * 26 self.wordEnd = False class Trie: def __init__(self): self.root = TrieNode() # Function to insert a key into the Trie def insert(self, key): currentNode = self.root for char in key: index = ord(char) - ord('a') if not currentNode.childNode[index]: currentNode.childNode[index] = TrieNode() currentNode = currentNode.childNode[index] currentNode.wordEnd = True # Function to search for a key in the Trie def search(self, key): currentNode = self.root for char in key: index = ord(char) - ord('a') if not currentNode.childNode[index]: return False currentNode = currentNode.childNode[index] return currentNode.wordEnd if __name__ == '__main__': trie = Trie() inputStrings = ['and', 'ant', 'do', 'geek', 'dad', 'ball'] # Insert each string into the Trie for word in inputStrings: trie.insert(word) searchQueryStrings = ['do', 'geek', 'bat'] # Search for each string and print whether it is found in the Trie for query in searchQueryStrings: print('Query String:', query) if trie.search(query): print('The query string is present in the Trie') else: print('The query string is not present in the Trie')>
자바스크립트
class TrieNode {  constructor() {  // Initialize the childNode array with 26 nulls  this.childNode = Array(26).fill(null);  // Initialize wordEnd to the false indicating that no word ends here yet  this.wordEnd = false;  } } class Trie {  constructor() {  // Initialize the root node of the Trie  this.root = new TrieNode();  }  // Function to insert a key into the Trie  insert(key) {  // Start from the root node  let currentNode = this.root;  for (let i = 0; i < key.length; i++) {  const index = key.charCodeAt(i) - 'a'.charCodeAt(0);  if (currentNode.childNode[index] === null) {  currentNode.childNode[index] = new TrieNode();  }  // Move to the next node in the Trie  currentNode = currentNode.childNode[index];  }  // Mark the end of the word  currentNode.wordEnd = true;  }  // Function to search for a key in the Trie  search(key) {  // Start from the root node  let currentNode = this.root;  // Iterate through each character in the key  for (let i = 0; i < key.length; i++) {  const index = key.charCodeAt(i) - 'a'.charCodeAt(0);  if (currentNode.childNode[index] === null) {  return false;  }  // Move to the next node in the Trie  currentNode = currentNode.childNode[index];  }  // Return true if the end of the word is marked otherwise false  return currentNode.wordEnd;  } } // Driver code const trie = new Trie(); const inputStrings = ['and', 'ant', 'do', 'geek', 'dad', 'ball']; // Insert each string into the Trie inputStrings.forEach((str) =>trie.insert(str)); const searchQueryStrings = ['do', 'geek', 'bat']; // 각 문자열을 검색하여 Trie에 있는지 여부를 인쇄합니다. searchQueryStrings.forEach((query) => { console.log(`Query String: ${query}`); if (trie.search(query)) { console.log('쿼리 문자열이 Trie에 있습니다.'); } else { console.log('쿼리 문자열이 Trie에 없습니다');>

산출
Query String: do The query string is present in the Trie Query String: geek The query string is present in the Trie Query String: bat The query string is not present in the Trie>

삭제 시도
  • Trie의 내용 표시
  • Trie를 이용한 자동완성 기능
  • 모든 접미사 트리를 사용한 패턴 검색
  • 연습 문제:

    • 최소 단어 나누기
    • 이진 행렬의 고유 행
    • 고유 하위 문자열 수
    • 워드 보글
    • Trie를 사용하여 문자열(또는 단어) 배열 정렬