본문 바로가기
::public/자료구조

이진 탐색 트리

by 해맑은욱 2019. 9. 3.

모든 노드는 유일한 키를 갖는다.

왼쪽 서브트리의 키들은 루트의 키보다 작다.

오른쪽 서브트리의 키들은 루트의 키보다 크다.

왼쪽과 오른쪽 서브트리도 이진 탐색 트리이다.

 

#include "BinaryTree.h"
 
class BinSrchTree : public BinaryTree
{
public:
     BinSrchTree(void) {}
     ~BinSrchTree(void) {}
 
    // 이진 탐색 트리의 탐색 연산
    BinaryNode* search(int key)
    {
        BinaryNode* node = searchRecur(root, key);
        if (node != NULL)
            printf("탐색 성공: 키값이 %d인 노드 있음\n", node->getData());
        else
            printf("탐색 실패: 키값이 %d인 노드 없음\n", key);
        return node;
    }
    // 키 값으로 노드를 탐색하는 함수(순환)
    BinaryNode* searchRecur(BinaryNode* n, int key)
    {
        if (n == NULLreturn NULL;
        if (key == n->getData())
            return n;
        else if (key < n->getData())
            return searchRecur(n->getLeft(), key);
        else
            return searchRecur(n->getRight(), key);
    }
 
    // 키 값으로 노드를 탐색하는 함수(반복)
    BinaryNode* searchIter(BinaryNode* n, int key)
    {
        while (n != NULL)
        {
            if (key == n->getData())
                return n;
            else if (key < n->getData())
                n = n->getLeft();
            else
                n = n->getRight();
        }
        return NULL// 탐색에 실패한 경우
    }
 
    
 
    // 이진 탐색 트리의 삽입 연산
    void insert(BinaryNode* n) 
    {
        if (n == NULLreturn;
        if (isEmpty()) root = n;
        else insertRecur(root, n);
    }
    // r을 루트로 갖는 서브트리에 새로운 노드 n을 삽입하는 함수(순환)
    void insertRecur(BinaryNode* r, BinaryNode* n)
    {
        if (n->getData() == r->getData())
            return;
        else if (n->getData() < r->getData())
        {
            if (r->getLeft() == NULL)
                r->setLeft(n);
            else
                insertRecur(r->getLeft(), n);
        }
        else
        {
            if (r->getRight() == NULL)
                r->setRight(n);
            else
                insertRecur(r->getRight(), n);
        }
    }
 
    // 이진 탐색 트리의 삭제 연산
    void remove(int data) 
    {
        if (isEmpty()) return// 빈 트리이면 return
 
        // 없앨 노드와 그 노드의 부모 노드를 찾는다.
        BinaryNode* parent = NULL;    // 없앨 노드의 부모
        BinaryNode* node = root;    // 없앨 노드
        while (node != NULL && node->getData() != key)
        {
            parent = node;
            node = (key < node->getData()) ? node->getLeft() : node->getRight();
        }
        // 없앨 노드가 트리에 없음
        if (node == NULL)
        {
            printf("Error: key is not in the tree!\n");
            return;
        }
        // 없앨 노드가 트리에 있음
        else remove(parent, node);
    }
    // parent를 부모로 갖는 노드 node를 이진 탐색 트리에서 삭제하는 함수.
    void remove(BinaryNode* parent, BinaryNode* node)
    {
        // 삭제하려는 노드가 단말 노드일 경우
        if (node->isLeaf())
        {
            if (parent == NULL)
                root = NULL;
            else
            {
                if (parent->getLeft() == node)
                    parent->setLeft(NULL);
                else
                    parent->setRight(NULL);
            }
        }
        // 삭제하려는 노드가 왼쪽이나 오른쪽 자식만 갖는 경우
        else if (node->getLeft() == NULL || node->getRight() == NULL)
        {
            // 삭제할 노드의 유일한 자식 노드 -> child
            BinaryNode* child = (node->getLeft() != NULL) ? node->getLeft() : node->getRight();
            // 삭제한 노드가 루트이면 -> child가 새로운 root가 됨
            if (node == root) root = child;
            // 아니면 -> 부모 노드의 자식으로 자식 노드 child를 직접 연결
            else
            {
                if (parent->getLeft() == node)
                    parent->setLeft(child);
                else
                    parent->setRight(child);
            }
        }
        // 삭제하려는 노드가 두개의 자식이 모두 있는 경우
        else
        {
            // 삭제하려는 노드의 오른쪽 서브트리에서 가장 작은 노드를 탐색
            // succ -> 후계 노드: 오른쪽 서브트리에서 가장 key가 작은 노드
            // succp -> 후계 노드의 부모 노드
            BinaryNode* succp = node;
            BinaryNode* succ = node->getRight();
            while(succ->getLeft() != NULL)    // 후계 노드 탐색
            {
                succp = succ;                // 후계 노드의 부모 노드
                succ = succ->getLeft();        // 후계 노드
            }
            // 후계 노드의 부모와 후계 노드의 오른쪽 자식을 직접 연결
            if (succp->getLeft() == succ)
                succp->setLeft(succ->getRight());
            else // 후계 노드가 삭제할 노드의 바로 오른쪽 자식인 경우
                succp->setRight(succ->getRight());
            // 후계 노드 정보를 삭제할 노드에 복사
            node->setData(succ->getData());
            // 삭제할 노드를 후계 노드로 변경: 실제로는 후계 노드가 제거됨
            node = succ;
        }
        delete node; // 메모리 동적 해제
    }
};
 
cs

'::public > 자료구조' 카테고리의 다른 글

우선순위 큐(STL 힙 정렬)  (0) 2019.09.03
우선순위 큐(힙)  (0) 2019.09.03
스레드 이진트리  (0) 2019.08.29
순환  (0) 2019.08.22
LinkedList 구현.  (0) 2019.08.21