1 분 소요

이진 검색 트리

정의와 성질

  • 정점(Vertex/Node): 트리에서 각 원소
  • 루트(Root): 트리에서 가장 꼭대기의 정점
  • 리프(leaf): 제일 말단에 위치해 자식이 없는 정점
  • 간선(Edge): 정점을 연결하는 선
  • 이진 트리(Binary Tree): 각 노드의 자식이 2개 이하인 트리
  • 이진 검색 트리(Binary Search Tree): 왼쪽 서브트리의 모든 값은 부모의 값보다 작고 오른쪽 서브트리의 모든 값은 부모의 값보다 큰 이진 트리
  • insert,erase,find,update: O(lgN)
  • 원소가 크기 순으로 정렬되어 있음

    자가 균형 트리

  • AVL트리, Red Black트리
  • STL에 있는 이진 검색 트리는 Red Black트리 이용

    Tip

  • unordered_set, unordered_map이 평균적으로 set,map보다 빠름 하지만 unordered_set, unordered_map은 충돌이 빈번하면 속도의 저하가 발생할 수 있음(O(N)이 될 수 있음)
  • set, map의 경우 O(lgN)이지만 같은 O(lgN)알고리즘들과 비교해서 많이 느림

    STL

  • Set
    #include<iostream>
    #include<set>
    using namespace std;
    int main(void){
      set<int> s;
      s.insert(-10);
      s.insert(100);
      s.insert(15);// {-10,15,100}
      s.insert(-10);// {-10,15,100}
      cout<<s.erase(100)<<'\n'; // 출력: 1 {-10,15}
      cout<<s.erase(20)<<'\n'; // 출력: 0 {-10,15}
      if(s.find(15)!=s.end()){
          cout<<"yes\n";
      }
      else{
          cout<<"no\n";
      }
      cout<<s.size()<<'\n'; // 2
      cout<<s.count(50)<<'\n';// 0
      for(auto e: s){
          cout<<e<<' '; //-10 15
      }
      cout<<'\n';
      s.insert(-40); // {-40,-10,15}
      set<int>::iterator it1 = s.begin();// {-40,-10,15}
      it1++;
      auto it2=prev(it1);
      it2=next(it1);
      advance(it2,-2); // 한 칸 움직일때 O(lgN) 현재는 O(lgN)*2
      auto it3 = s.lower_bound(-20);
      auto it4 = s.find(15);
      cout<<*it1<<'\n';// -10
      cout<<*it2<<'\n';// -40
      cout<<*it3<<'\n';// -10
      cout<<*it4<<'\n';// 15
      return 0;
    }
    
  • Multiset
    #include<iostream>
    #include<set>
    using namespace std;
    int main(void){
      multiset<int> ms;
      ms.insert(-10);
      ms.insert(100);
      ms.insert(15);// {-10,15,100}
      ms.insert(-10);// {-10,-10,15,100}
      ms.insert(15);// {-10,-10,15,15,100}
      cout<<ms.size()<<'\n';// 5
      for(auto e:ms){
          cout<<e<<' '; // -10 -10 15 15 100
      }
      cout<<'\n';
      cout<<ms.erase(15)<<'\n'; // 출력: 2 {-10,-10,100}
      ms.erase(ms.find(-10)); //{-10,100}
      ms.insert(100);//{-10,100,100}
      cout<<ms.count(100)<<'\n';// 2
      auto it1 = ms.begin();
      auto it2 = ms.upper_bound(100);
      auto it3 = ms.find(100);
      cout<<*it1<<'\n';// -10
      cout<<(it2==ms.end())<<'\n';// 1 end를 가리키고 있으므로 *it2를 출력하면 에러 발생
      cout<<*it3<<'\n';// 100
      return 0;
    }
    
  • Map
    #include<iostream>
    #include<map>
    using namespace std;
    int main(void){
      map<string,int> m;
      m["hi"]=123;
      m["bird"]=1000;
      m["gogo"]=165; //{"bird",1000},{"gogo",165},{"hi",123}
      cout<<m.size()<<'\n'; //3
      m["hi"]=-7; //{"bird",1000},{"gogo",165},{"hi",-7}
      if(m.find("hi")!=m.end()){
          cout<<"yes\n";
      }
      else{
          cout<<"no\n";
      }
      m.erase("bird");//{"gogo",165},{"hi",-7}
      for(auto e:m){
          cout<<e.first<<' '<<e.second<<'\n'; //gogo 165
                                              //hi -7
      }
      auto it1 = m.find("gogo");
      cout<<it1->first<<' '<<it1->second<<'\n';// gogo 165
      return 0;
    }