검색 나무 지원을 세 가지 주요 작업:요소의 삽입,삭제의 요소,그리고 조회(는지 여부를 확인하는 키가 현재).
SearchingEdit
중에서 검색을 위해 나무는 특정 키 프로그래밍할 수 있습을 재귀적으로 또는 반복적으로.
우리는 루트 노드를 검사하여 시작합니다. 트리가 null 이면 우리가 검색하는 키가 트리에 존재하지 않습니다. 그렇지 않으면 키가 루트의 키와 같으면 검색이 성공하고 노드를 반환합니다. 키가 루트보다 작 으면 왼쪽 하위 트리를 검색합니다., 마찬가지로 키가 루트보다 크면 오른쪽 하위 트리를 검색합니다. 이 프로세스는 키를 찾거나 나머지 하위 트리가 널이 될 때까지 반복됩니다. 널 하위 트리에 도달 한 후 검색된 키를 찾을 수 없으면 키가 트리에 없습니다. 이것은 쉽게 표현으로 재귀적 알고리즘(에서 구현 Python):
동일한 알고리즘을 구현할 수 있습 반복적으로.
이러한 두 가지 예를 지원하지 않 중복되는,그들은 의존하는 순서에 관계되는 총 순서입니다.
재귀 알고리즘은 꼬리 재귀 적이라는 것을 알 수 있습니다., 꼬리 호출 최적화를 지원하는 언어에서 재귀 및 반복 예제는 동등한 프로그램으로 컴파일됩니다.
기 때문에 최악의 경우에는 이 알고리즘을 검색해야 합니다 뿌리에서 나무의 잎을 가장 먼 곳에서 루트,검색 작업에 소요 시간에 비례하는 나무의 높이(참조하십시오 나무용어). 평균적으로 노드 키가있는 이진 검색 트리에는 o(log|Nodes|)높이가 있습니다. 그러나,최악의 경우에는 검색 나무 있을 수 있습 O(|노드|)높이면서 불균형과 유사한 나무 목록(타락한 트리).,
중복 allowedededit 로 검색
주문 관계가 총 선주문 일 경우 기능의 합리적인 확장은 다음과 같습니다. 따라서 트리의 모든 중복의 오른쪽 또는 왼쪽에 중복을 삽입 할 방향(또는 하드 와이어)을 지정할 수 있습니다. 경 방향 하드 와이어드 모두 선택,오른쪽과 왼쪽의 지원으로 삽입으로 복제 밀어 작업 및 삭제로 pop 작업입니다.,:155
이러한 검색 기능을 갖춘 이진 트리 정렬이 안정됩니다.
insertionedit
검색이 시작될 때 삽입이 시작됩니다. 결국 우리에 도달 할 것이 외부 노드를 추가하는 새로운 key-value pair(여기서로 인코딩 기록’newNode’)으로 오른쪽 또는 왼쪽으로 자식에 따라 노드의 열쇠이다., 다시 말해서,우리는 루트 및을 재귀적으로 삽입하는 새로운 노드의 왼쪽 하위트리하면 그것의 키보의 뿌리거나,오른쪽 하위 트리는 경우 키 보다 크거나 같은 루트입니다.
여기에는 방법이 일반적인 검색 트리에 삽입될 수 있습에서 수행되는 바이너리에서는 C++:
또는 비 재귀 버전을 구현할 수 있습니다., 를 사용하여 포인터 를 우리는 어디에서 왔는지할 수 있는 코드를 방지하는 명시적 검사 및 처리의 경우 필요가 있는 곳에 삽입하는 노드 트리 루트:
위의 파괴적인 절차적인 변종이 수정 나무에다. 상수 힙 공간 만 사용하지만(반복 버전도 상수 스택 공간을 사용합니다)이전 버전의 트리는 손실됩니다., 또는,다음과 같이 파이썬를 들어,우리는 재구성 할 수 있습니다 모든 조상의 삽입된 노드를 참조하는 모든 원래 트리 루트 유효기 나무는 영구적인 데이터 구조
는 부분이 재건 사 O(로그 n)공간에서 평균을 경우 O(n)에서 최악의 경우입니다.
버전 중 하나에서,이 작업에 필요한 시간에 비례하는 나무의 높이 최악의 경우에는 O(로그 n)시간에서 평균 경우 모든 나무하지만,O(n)시간에 최악의 경우입니다.,
하는 또 다른 방법을 설명 삽입하기 위해서는 삽입하는 새로운 노드 트리에서,그 키를 처음에 비해 루트입니다. 그 키가 루트의 키보다 작 으면 루트의 왼쪽 자식의 키와 비교됩니다. 키가 큰 경우 루트의 오른쪽 자식과 비교됩니다. 이 과정이 계속될 때까지 새로운 노드가 비교 잎으로 노드,그리고 그것은 추가로 이 노드의 오른쪽 또는 왼쪽으로 자식에 따라,그것의 주요한 경우:키 보다 작은 잎의 주요,그 다음 그것으로 삽입 잎의 왼쪽에 아동,그렇지 않으면 잎의 오른쪽 아이입니다.,
있는 다른 방법으로 삽입하는 노드로 이진 나무,그러나 이것은 유일한 방법으로 삽입하는 노드에 잎과 동시에 유지 BST 구조입니다.
DeletionEdit
제거할 경우 노드에서 이진 검색 나무 아래의 레크리에이션 활동은 유지에서 순서의 노드입니다. 이 작업을 수행 할 수있는 많은 가능성이있다. 그러나 다음과 같은 방법을 제안되었으로 1962 년에 그의 가족사진이 눈길을 끕니다 보장하는 높이의 주제는 하위 트리에 의해 변경되는 대부분에 하나입니다., 고려해야 할 세 가지 가능한 경우가 있습니다.
- 자식이없는 노드 삭제:단순히 트리에서 노드를 제거하십시오.
- 한 자식으로 노드 삭제:노드를 제거하고 자식으로 바꿉니다.
- 두 자식을 가진 노드 D 삭제:D 의 순서 전임자 또는 순서 후임자 E 중 하나를 선택합니다(그림 참조). 을 삭제하는 대신 D,덮어 그것의 키와 값을 가진 전자니다. 는 경우 전자가 없는 아이는 제거,E 이전 부모 G. 경우 전자가 아 F,그것은 바로 아이다,그래서 그것을 대체하는 E 에서 전자의 부모입니다.,
노드를 삭제하는 두 아이들과 함께서는 바이너리 검색 나무입니다. 먼저 오른쪽 하위 트리의 가장 왼쪽 노드 인 순서 후속 E 가 식별됩니다. 그 값은 삭제되는 노드 D 에 복사됩니다. 그런 다음 주문 후속작은 대부분 한 명의 자녀가 있기 때문에 쉽게 삭제할 수 있습니다. 동일한 방법은 대칭으로 사용하기 위해 이전 C.
모든 경우에,D 때 발생하는 루트,교체 노드 루트 again.
두 자식을 가진 노드는 삭제하기가 더 어렵습니다., 노드의 순서는 후계자가 그 권리는 하위의 가장 왼쪽의 자녀,그리고 노드의 주문 이전은 왼쪽 하위의 가장 오른쪽 아이입니다. 두 경우 모두이 노드에는 자식이 하나 또는 전혀 없습니다. 위의 두 가지 간단한 경우 중 하나에 따라 삭제하십시오.
지속적으로 사용하기 위하여 후계자의 주문 이전의 모든 인스턴스에 대해 두 자녀의 경우 이어질 수 있는 불균형 트리,그래서 일부 구현을 선택 중 하나 또는 다른 다른 시간에.,
런타임이 분석:이 동작하지 않을 통과 나무 잎,이것은 항상 가능성;따라서 최악의 경우에 필요한 시간에 비례하는 고도의 나무. 그것을 필요로하지 않는 더 많은 경우에도 노드에는 두 아이들 때문에,그것은 여전히 다음과 같이 단일 경로를 방문 하지 않는 모든 노드가 두 번.,
TraversalEdit
한 번의 검색 트리를 만든 요소를 검색할 수 있습에서 순서에 의해 재귀적으로 통과하의 왼쪽 하위 트리 루트 노드에 액세스하는 노드 자체는 다음을 재귀적으로 통과하는 권리 하위 노드의 계속이 패턴으로 각 노드 트리에 있는 그것의 재귀적으로 액세스합니다. 으로 모든 바이너리,나무 하나를 수행할 수 있습 pre-기 위해 통과 또는 게시물 주문을 통과,그러나 가능성이 높은 유용성에 대한 검색 나무., In-기 위해 탐색의 검색 트리에서 항상 발생 정렬된 목록의 노드 항목(숫자,문자열,또는 다른 유사한 품목).
파이썬에서의 순서 순회에 대한 코드는 아래에 나와 있습니다. 그것은 호출을 콜백(어떤 기능을 프로그래머 소원을 호출 노드의 값은 같은 인쇄 화면)에 위한 모든 노드 트리에서.
순회에는 모든 노드를 방문해야하기 때문에 O(n)시간이 필요합니다. 이 알고리즘은 또한 O(n)이므로 점근 적으로 최적입니다.
순회도 반복적으로 구현할 수 있습니다. 특정 응용 프로그램의 경우,예를 들어, 더 큰 동일 검색,근사 검색,단일 단계(반복)순회에 대한 작업이 매우 유용 할 수 있습니다. 이것은 물론 콜백 구조체없이 구현되며 평균적으로 o(1)를 취하고 최악의 경우 o(log n)를 취합니다.
VerificationEdit
때때로 우리는 이미 이진 나무,그리고 우리는지 여부를 결정하는 BST. 이 문제에는 간단한 재귀 솔루션이 있습니다.,
BST 속성—모든 노드에서 오른쪽 하위 트리하는 것보다 더 큰 현재 노드 및 모든 노드에 왼쪽 하위트리에는 작은 것보다 현재 노드입니다 핵심을 파악하는지 여부 나무는 BST 나지 않습니다. 욕심 많은 알고리즘—단순히 통과 나무에서,모든 노드는지 여부를 확인 노드의 값이 포함되어 보다 큰 값이 왼쪽에 있는 아이보다 작은 값이 오른쪽에 아동을 위해 작동하지 않는 경우도 있습니다., 다음 사항을 고려나무
20 / \ 10 30 / \ 5 40
에서는 나무 위의 각 노드를 조건을 충족하는 노드가 포함되어 보다 큰 값이 왼쪽에 아동하고 보다 작은 오른쪽 아이 잡고,아직 그것은 BST:값 5 은 오른쪽에 subtree 의 노드를 포함한 20 일의 위반을 조정할 수 있는 유연성을 제공합니다.
노드와 그 자식의 값만을 기반으로 결정을 내리는 대신 부모로부터도 아래로 흐르는 정보가 필요합니다., 위의 트리의 경우 값 20 을 포함하는 노드에 대해 기억할 수 있다면 값 5 를 가진 노드가 BST 속성 계약을 위반하고 있음을 알 수 있습니다.,
의 조건을 확인해야에서는 각 노드입니다:
- 경우 노드의 왼쪽에 아이의 부모로,그것보다 작아야 합니다(또는 동등한 것)부모 및 전달해야 합 가치 아래 부모로부터 오른쪽 하위 트리를 만들의 노드에 하위트리보다 더 큰 부모
- 경우 노드입니다 오른쪽에 아이의 부모, 그 다음은 보다 커야 합니다 부모 및 전달해야 합 가치 아래서 부모의 왼쪽 하위트리의 아무도 확인하기 위하여 노드에 하위트리보다 적은 부모이다.,
재귀적 솔루션에서는 C++를 이것을 설명한다.
node->key+1
및node->key-1
수행할 수 있도록 고유한 요소에 BST.
동일한 요소도 존재하기를 원한다면 두 곳에서node->key
만 사용할 수 있습니다.
초기 호출하여 이 기능은 같은 것을 할 수 있습니다:
if (isBST(root, INT_MIN, INT_MAX)) { puts("This is a BST.");} else { puts("This is NOT a BST!");}
기본적으로 우리가 만들어서 유효한 범위(에서 시작하는)그리고 계속 줄을 내려 각 노드로 우리는 아래로 이동 재귀적으로.,
섹션#순회 에서 지적한 바와 같이 이진 검색 트리의 순서 순회는 정렬 된 노드를 반환합니다. 따라서 우리를 유지할 필요가 마지막으로 방문한 노드를 순회하면서 나무와 여부를 확인 그것의 키가 작게(또는 작/동일한 경우 중복하여 수리)에 비해 현재의 열쇠이다.
병렬 algorithmsEdit
도 있 병렬 알고리즘에 대한 검색 나무 포함하여 삽입/삭제하는 여러 요소,건설,배열에서,필터를 특정드 시원을 평평하게 배열,병합/뺀/교차하는 두 나무,등등., 이 알고리즘을 구현할 수 있을 사용하여 가입하세 기반 트리 알고리즘을 유지할 수 있습 트리의 균형을 사용하여 여러 가지 분산 스키마(비롯 AVL 트리지만,무게의 균형 트리 treap). 피>