std :: map이 레드-블랙 트리로 구현 된 이유는 무엇입니까? 균형 잡힌 이진 검색 트리 (BST)가 있습니다.

레드-블랙 트리std::map 로 구현 된 이유는 무엇 입니까?

몇 가지 균형 잡힌 이진 검색 트리 (BST)가 있습니다. 레드-블랙 트리를 선택할 때 디자인 트레이드 오프는 무엇입니까?



답변

아마도 가장 일반적인 두 가지 자체 밸런싱 트리 알고리즘은 Red-Black 트리AVL 트리 입니다. 삽입 / 업데이트 후 트리의 균형을 맞추기 위해 두 알고리즘 모두 트리의 노드가 회전되어 재 밸런싱을 수행하는 회전 개념을 사용합니다.

두 알고리즘 모두 삽입 / 삭제 작업은 O (log n)이지만, Red-Black tree 리 밸런싱 회전의 경우 회전은 O (1) 작업이며 AVL에서는 O (log n) 작업입니다. 재조정 단계의이 측면에서 레드-블랙 트리가 더 효율적이며 더 일반적으로 사용되는 가능한 이유 중 하나입니다.

Red-Black 트리는 Java 및 Microsoft .NET Framework의 제품을 포함하여 대부분의 컬렉션 라이브러리에서 사용됩니다.


답변

실제로 사용법에 따라 다릅니다. AVL 트리는 일반적으로 재조정의 회전이 더 많습니다. 따라서 응용 프로그램에 삽입 및 삭제 작업이 너무 많지 않지만 검색시 가중치가 큰 경우 AVL 트리가 적합합니다.

std::map Red-Black 트리는 노드 삽입 / 삭제 속도와 검색 속도 사이에서 적절한 균형을 유지하므로 Red-Black 트리를 사용합니다.


답변

AVL 트리의 최대 높이는 1.44logn이고 RB 트리의 최대 높이는 2logn입니다. AVL에 요소를 삽입하면 트리의 한 지점에서 균형이 다시 잡힐 수 있습니다. 리 밸런싱이 삽입을 완료합니다. 새 리프를 삽입 한 후에는 해당 리프의 상위 항목을 루트까지 또는 두 하위 트리의 깊이가 같은 지점까지 업데이트해야합니다. k 개의 노드를 업데이트해야 할 확률은 1 / 3 ^ k입니다. 재조정은 O (1)입니다. 요소를 제거하면 둘 이상의 재조정 (나무 깊이의 최대 절반)이 포함될 수 있습니다.

RB- 트리는 이진 검색 트리로 표시되는 차수 4의 B- 트리입니다. B- 트리의 4 노드는 동등한 BST에서 두 가지 수준으로 나타납니다. 최악의 경우 트리의 모든 노드는 2 노드이며 3 노드 체인 하나만 잎사귀로 만듭니다. 그 잎은 뿌리에서 2log 떨어진 거리에 있습니다.

루트에서 삽입 지점으로 내려 가면 4 개의 노드를 2 개의 노드로 변경하여 삽입으로 리프가 포화되지 않도록해야합니다. 삽입에서 돌아와서이 모든 노드는 4 노드를 올바르게 나타내는 지 확인해야합니다. 이것은 트리에서 내려갈 수도 있습니다. 글로벌 비용은 동일합니다. 무료 점심은 없습니다! 트리에서 요소를 제거하는 순서는 같습니다.

이 모든 나무들은 노드가 높이, 무게, 색상 등에 관한 정보를 가지고 있어야합니다. Splay 나무 만이 그러한 추가 정보가 없습니다. 그러나 대부분의 사람들은 구조의 난폭성 때문에 스플레이 트리를 두려워합니다!

마지막으로 트리는 노드에 가중치 정보를 전달하여 가중치 균형을 조정할 수 있습니다. 다양한 방식이 적용될 수 있습니다. 하위 트리에 다른 하위 트리의 요소 수의 3 배 이상이 포함되어 있으면 균형을 다시 조정해야합니다. 재조정은 단일 회전 또는 이중 회전을 통해 다시 수행됩니다. 이것은 최악의 경우 2.4logn을 의미합니다. 훨씬 더 좋은 비율 인 3 대신 2 배로 벗어날 수 있지만, 여기저기서 하위 트리의 1 %보다 약간 적은 균형을 유지하는 것을 의미 할 수 있습니다. 교활한!

어떤 종류의 나무가 가장 좋습니까? 확실히 AVL. 코드를 작성하는 것이 가장 간단하고 최악의 높이를 기록 할 수 있습니다. 1000000 개의 요소로 구성된 트리의 경우 AVL은 높이에 따라 높이 29, RB 40 및 가중치 균형이 36 또는 50입니다.

임의성, 추가 비율, 삭제 비율, 검색 등의 다른 변수가 많이 있습니다.


답변

위의 답변은 트리 대안 만 다루고 빨간색은 아마도 역사적인 이유로 남아있을 것입니다.

왜 해시 테이블이 아닌가?

유형은 <연산자 (비교) 만 트리의 키로 사용해야합니다. 그러나 해시 테이블에는 각 키 유형에 hash함수가 정의 되어 있어야합니다 . 일반적인 프로그래밍에서는 유형 요구 사항을 최소로 유지하는 것이 매우 중요하므로 다양한 유형 및 알고리즘과 함께 사용할 수 있습니다.

좋은 해시 테이블을 디자인하려면 사용될 컨텍스트에 대한 친밀한 지식이 필요합니다. 개방형 주소 지정 또는 연결된 체인을 사용해야합니까? 크기를 조정하기 전에 어떤 수준의 부하를 수용해야합니까? 충돌을 피하는 고가의 해시 또는 거칠고 빠른 해시를 사용해야합니까?

STL은 애플리케이션에 가장 적합한 선택을 예상 할 수 없으므로 기본값이 더 유연해야합니다. 나무는 “그냥 작동”하고 잘 확장됩니다.

(C ++ 11은을 사용하여 해시 테이블을 추가했습니다 unordered_map. 설명서 에서 이러한 많은 옵션을 구성하기 위해 정책을 설정해야한다는 것을 알 수 있습니다.)

다른 나무는 어떻습니까?

레드 블랙 트리는 BST와 달리 빠른 조회를 제공하고 자체 균형을 유지합니다. 다른 사용자는 자체 균형 AVL 트리보다 장점을 지적했습니다.

Alexander Stepanov (STL의 창시자)는 std::map다시 쓰면 레드-블랙 트리 대신 B * 트리를 사용할 것이라고 말했다 . 현대 메모리 캐시에 더 친숙하기 때문이다.

그 이후로 가장 큰 변화 중 하나는 캐시의 성장이었습니다. 캐시 미스는 비용이 많이 들기 때문에 참조의 지역성이 훨씬 중요합니다. 참조 지역성이 낮은 노드 기반 데이터 구조는 훨씬 덜 이해됩니다. 오늘 STL을 디자인하고 있다면 다른 컨테이너 세트가있을 것입니다. 예를 들어, 인 메모리 B *-트리는 연관 컨테이너를 구현하기 위해 레드-블랙 트리보다 훨씬 낫습니다. – 알렉산더 스테파노 프

지도는 항상 나무를 사용해야합니까?

또 다른 가능한 맵 구현은 정렬 된 벡터 (삽입 정렬) 및 이진 검색입니다. 이것은 자주 수정되지는 않지만 자주 쿼리되는 컨테이너에는 효과적입니다. 나는 종종 C에서이 작업을 수행 qsort하고 bsearch내장되어 있습니다.

지도를 사용해야합니까?

캐시 고려 사항은 학교에서 배운 상황 (예 : 목록의 중간에서 요소를 제거하는 경우)에 사용 std::list하거나 그 std::deque이상 사용하는 것이 거의 의미가 없음을 의미합니다 std:vector. 동일한 추론을 적용하면서 for 루프를 사용하여 목록을 선형 검색하는 것이 몇 가지 조회를 위해 맵을 작성하는 것보다 더 효율적이고 깔끔합니다.

물론 읽기 가능한 컨테이너를 선택하는 것이 일반적으로 성능보다 중요합니다.


답변

2017-06-14 업데이트 : webbertiger는 댓글을 달고 답변을 편집합니다. 나는 그 대답이 이제 내 눈에 훨씬 나아 졌다는 것을 지적해야한다. 그러나 나는 추가 정보처럼 대답을 유지했습니다 …

첫 번째 답변이 잘못되었다고 생각하기 때문에 (수정 : 더 이상 둘다는 아님) 세 번째 답변에는 잘못된 확인이 있습니다. 나는 물건을 명확히해야한다고 생각합니다 …

가장 인기있는 2 개의 트리는 AVL과 Red Black (RB)입니다. 주요 차이점은 활용률에 있습니다.

  • AVL : 상담 비율 (읽기)이 조작 (수정)보다 큰 경우에 좋습니다. 메모리 풋 프린트는 RB보다 약간 적습니다 (컬러에 필요한 비트로 인해).
  • RB : 상담 (읽기)과 조작 (수정) 또는 상담에 대한 수정 사이에 균형이있는 일반적인 경우에 더 좋습니다. 레드-블랙 플래그 저장으로 인해 약간 더 큰 메모리 풋 프린트.

주요 차이점은 채색에서 비롯됩니다. RB 트리에서 AVL보다 재조정 작업이 적습니다. 색상을 사용하면 상대적으로 높은 비용이 드는 재조정 작업을 건너 뛰거나 짧게 할 수 있기 때문입니다. 채색으로 인해 RB 트리는 검은 색 노드 사이에 빨간 노드를 수용 할 수 있기 때문에 (~ 2 배 더 많은 가능성을 가짐) 검색 효율을 조금 떨어 뜨릴 수 있기 때문에 노드 레벨이 더 높습니다. 상수 (2x), O (log n)에 유지됩니다.

트리 수정에 대한 성능 적중 (유의 한) 대 트리에 대한 상담의 성능 적중 (거의 중요하지 않은)을 고려하면 일반적인 경우 AVL보다 RB를 선호하는 것이 당연합니다.


답변

그것은 당신의 구현의 선택 일뿐입니다-그것들은 균형 잡힌 나무로 구현 될 수 있습니다. 다양한 선택은 모두 약간의 차이와 비슷합니다. 그러므로 어느 것이나 다른 것만 큼 좋습니다.


답변