나는 Haskell을 배우고 운동으로 이진 트리를 만들고 있습니다. 정기적 인 이진 트리를 만들었으므로 자체 균형 조정에 맞게 조정하고 싶습니다. 그래서:
- 어느 것이 가장 효율적인가요?
- 어느 것이 가장 구현하기 쉬운가?
- 어느 것이 가장 자주 사용됩니까?
그러나 결정적으로, 당신은 어느 것을 추천합니까?
토론이 가능하기 때문에 여기에 있다고 가정합니다.
나는 Haskell을 배우고 운동으로 이진 트리를 만들고 있습니다. 정기적 인 이진 트리를 만들었으므로 자체 균형 조정에 맞게 조정하고 싶습니다. 그래서:
그러나 결정적으로, 당신은 어느 것을 추천합니까?
토론이 가능하기 때문에 여기에 있다고 가정합니다.
답변:
Red-Black tree 또는 AVL tree로 시작하는 것이 좋습니다 .
레드-블랙 트리는 삽입 속도가 빠르지 만 AVL 트리는 조회를 위해 약간의 가장자리가 있습니다. AVL 트리는 구현하기가 다소 쉬울 수 있지만 내 경험을 바탕으로 한 것은 아닙니다.
AVL 트리는 각 삽입 또는 삭제 후 트리가 균형을 유지하도록합니다 (하위 트리는 1 / -1보다 큰 균형 계수를 갖지 않는 반면, 빨강-검정 트리는 트리가 항상 균형을 유지하도록합니다.
무작위 데이터 구조에 문제가 없다면 대안을 고려할 것입니다 : Skip Lists .
높은 수준의 관점에서 볼 때 트리 구조는 트리로 구현되지 않고 여러 계층의 링크가있는 목록으로 구현된다는 점을 제외하면 트리 구조입니다.
O (log N) 삽입 / 검색 / 삭제가 발생하므로 까다로운 재조정 사례를 모두 처리하지 않아도됩니다.
함수형 언어로 구현하는 것을 고려한 적이 없으며 wikipedia 페이지에 아무것도 표시되지 않으므로 쉽지 않을 수 있습니다 (불변)
상대적으로 쉬운 구조로 시작하려는 경우 (AVL 트리와 빨강-검정 트리 모두 미묘하게), 하나의 옵션은 "tree"와 "heap"의 조합으로 명명 된 treap입니다.
각 노드는 "우선 순위"값을 얻습니다. 종종 노드가 생성 될 때 무작위로 할당됩니다. 노드는 키 순서가 존중되고 힙과 같은 우선 순위 값의 순서가 존중되도록 트리에 배치됩니다. 힙과 같은 순서는 부모의 두 자녀가 부모보다 우선 순위가 낮다는 것을 의미합니다.
위의 "키 값 내"에서 삭제 된 편집 -우선 순위와 키 순서가 함께 적용되므로 고유 키의 경우에도 우선 순위가 중요합니다.
흥미로운 조합입니다. 키가 고유하고 우선 순위가 고유 한 경우 모든 노드 세트에 고유 한 트리 구조가 있습니다. 그럼에도 불구하고 삽입 및 삭제가 효율적입니다. 엄밀히 말하면 트리는 효과적으로 연결된 목록 인 지점까지 균형을 맞출 수 없지만 표준 이진 트리와 달리 순서대로 삽입 된 키와 같은 일반적인 경우를 포함하여 (표준 이진 트리와 같이) 극히 가능성이 적습니다.
어느 것이 가장 효율적인가요?
모호하고 대답하기 어렵다. 계산 복잡성은 모두 잘 정의되어 있습니다. 그것이 효율성이라는 의미라면 실제 토론은 없습니다. 실제로 모든 좋은 알고리즘에는 증거와 복잡성 요소가 있습니다.
"런타임"또는 "메모리 사용"을 의미하는 경우 실제 구현을 비교해야합니다. 그런 다음 언어, 런타임, OS 및 기타 요소가 작용하여 질문에 대답하기가 어렵습니다.
어느 것이 가장 구현하기 쉬운가?
모호하고 대답하기 어렵다. 일부 알고리즘은 복잡해 보이지만 나에게는 사소한 것입니다.
어느 것이 가장 자주 사용됩니까?
모호하고 대답하기 어렵다. 먼저 "누가?" 이것의 일부? 하스켈 만? C 또는 C ++는 어떻습니까? 둘째, 설문 조사를 위해 소스에 액세스 할 수없는 독점 소프트웨어 문제가 있습니다.
그러나 결정적으로, 당신은 어느 것을 추천합니까?
토론이 가능하기 때문에 여기에 있다고 가정합니다.
옳은. 다른 기준은 그다지 도움이되지 않기 때문에 이것이 전부입니다.
많은 수의 트리 알고리즘에 대한 소스를 얻을 수 있습니다. 무언가를 배우고 싶다면 찾을 수있는 모든 것을 간단하게 구현할 수 있습니다. "권장"을 요청하는 대신 찾을 수있는 모든 알고리즘을 수집하십시오.
목록은 다음과 같습니다.
http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
6 개의 인기있는 것들이 정의되어 있습니다. 그것들로 시작하십시오.
Splay 나무에 관심이 있다면 Allen과 Munroe의 논문에서 처음으로 묘사 된 것보다 간단한 버전이 있습니다. 동일한 성능 보장은 없지만 "zig-zig"와 "zig-zag"재조정을 처리 할 때 복잡성을 피할 수 있습니다.
기본적으로, 검색 할 때 (삽입 지점 또는 삭제할 노드 검색 포함) 찾은 노드는 루트쪽으로 바로 회전합니다 (예 : 재귀 검색 기능이 종료 됨). 각 단계에서 루트쪽으로 다른 단계를 끌어 올리려는 자식이 오른쪽 자식인지 왼쪽 자식인지에 따라 단일 왼쪽 또는 오른쪽 회전을 선택합니다 (회전 방향을 올바르게 기억하면 각각 다릅니다).
Splay 트리와 마찬가지로 최근에 액세스 한 항목은 항상 트리의 루트 근처에 있으므로 다시 빠르게 액세스 할 수 있습니다. 이 Allen-Munroe 회전식 루트 (더 이상 공식 이름을 모르는)는 더 간단 할 수 있지만 더 빠른 성능 보증을 제공하지는 않습니다.
한 가지-정의에 의한이 데이터 구조는 찾기 작업에도 영향을 미치기 때문에 아마도 모나드 방식으로 구현해야 할 것입니다. 기능 프로그래밍에는 적합하지 않을 수 있습니다.