배열
에서만 사용할 수 있다.// BinarySearchTree.h
#pragma once
struct Node {
int Data = 0;
Node* Parent = nullptr;
Node* LeftChild = nullptr;
Node* RightChild = nullptr;
};
class BinarySearchTree
{
private:
Node* mRoot;
public:
BinarySearchTree() {
mRoot = nullptr;
}
void Insert(int data); // 삽입
Node* Search(Node* node, int data); // 탐색
void Replace(Node* u, Node* v); // 트리 교체
void Delete(int data); // 삭제
void Delete(Node* node); // 삭제
Node* Min(Node* node); // 최솟값
Node* Max(Node* node); // 최댓값
Node* Next(Node* node); // 다음 값
void Print(Node* node); // 트리 출력(중위 순회)
Node* GetRoot(); // 루트 노드 반환
};
// BinarySearchTree.cpp
#include <iostream>
#include "BinarySearchTree.h"
using namespace std;
/// <summary>
/// 데이터 삽입 함수
/// </summary>
/// <param name="삽입할 데이터"></param>
void BinarySearchTree::Insert(int data)
{
Node* newNode = new Node;
newNode->Data = data;
if (!mRoot) // root가 없으면
{
mRoot = newNode;
return;
}
Node* node = mRoot;
Node* parent = nullptr;
while (node)
{
parent = node;
if (parent->Data > data)
node = parent->LeftChild;
else
node = parent->RightChild;
}
newNode->Parent = parent;
if (data < parent->Data)
parent->LeftChild = newNode;
else
parent->RightChild = newNode;
}
/// <summary>
/// 이진 트리 탐색 함수
/// </summary>
/// <param name="루트 노드"></param>
/// <param name="탐색할 데이터"></param>
/// <returns>탐색할 데이터의 노드</returns>
Node* BinarySearchTree::Search(Node* node, int data)
{
// 못 찾으면 nullptr
if (!node || node->Data == data)
return node;
// node의 data보다 작으면 왼쪽
if (node->Data > data)
return Search(node->LeftChild, data);
// 그 외는 오른쪽
else
return Search(node->RightChild, data);
}
/// <summary>
/// 서브 트리 교체 함수
/// </summary>
/// <param name="삭제한 노드"></param>
/// <param name="이어 붙일 노드"></param>
void BinarySearchTree::Replace(Node* deleteNode, Node* attachNode)
{
if (!deleteNode->Parent) // deleteNode가 루트 노드라면
mRoot = attachNode;
else if (deleteNode->Parent->LeftChild == deleteNode) // deleteNode가 왼쪽 노드라면
deleteNode->Parent->LeftChild = attachNode;
else // deleteNode가 오른쪽 노드라면
deleteNode->Parent->RightChild = attachNode;
// nullptr 예외 처리
if (attachNode)
attachNode->Parent = deleteNode->Parent;
delete deleteNode;
}
/// <summary>
/// 원하는 데이터의 노드 삭제
/// </summary>
/// <param name="삭제할 데이터"></param>
void BinarySearchTree::Delete(int data)
{
Node* deleteNode = Search(mRoot, data);
Delete(deleteNode);
}
/// <summary>
/// 노드 삭제 함수
/// </summary>
/// <param name="삭제할 노드"></param>
void BinarySearchTree::Delete(Node* node)
{
if (!node)
return;
// 자식 여부에 따라 분기
if (!node->LeftChild) // 왼쪽 자식이 없을 때
Replace(node, node->RightChild);
else if (!node->RightChild) // 오른쪽 자식이 없을 때
Replace(node, node->LeftChild);
else
{
Node* next = Next(node);
node->Data = next->Data;
Delete(next);
}
}
/// <summary>
/// 트리의 최솟값을 찾는 함수
/// </summary>
/// <param name="루트 노드"></param>
/// <returns>트리의 최솟값</returns>
Node* BinarySearchTree::Min(Node* node)
{
if (!node) // 노드가 없으면 nullptr
return nullptr;
while (node->LeftChild) // 가장 작은 값 찾기
node = node->LeftChild;
return node;
}
/// <summary>
/// 트리의 최댓값을 찾는 함수
/// </summary>
/// <param name="node">루트 노드</param>
/// <returns>트리의 최댓값</returns>
Node* BinarySearchTree::Max(Node* node)
{
if (!node) // 노드가 없으면 nullptr
return nullptr;
while (node->RightChild) // 가장 큰 값 찾기
node = node->RightChild;
return node;
}
/// <summary>
/// 해당 노드 기준으로 바로 다음 값(큰 값)을 찾는 함수
/// </summary>
/// <param name="다음 값을 찾을 노드"></param>
/// <returns>해당 노드의 다음으로 큰 노드 반환</returns>
Node* BinarySearchTree::Next(Node* node)
{
// 오른쪽 자식 노드 있으면 오른쪽 자식 노드 트리에서 최솟값 반환(next 값)
if (node->RightChild)
return Min(node->RightChild);
Node* parent = node->Parent;
// 부모 노드가 존재하고, 현재 노드가 부모 노드의 오른쪽 자식일 때
// 오른쪽 자식이 아닌 부모 노드까지 올라간 후, 그 노드의 부모 노드(next 값) 반환
while (parent && node == parent->RightChild)
{
node = parent;
parent = node->Parent;
}
// 현재 노드가 왼쪽 자식이면 어떠한 분기도 거치지 않고 바로 부모 노드(next 값) 반환
return parent;
}
/// <summary>
/// 트리 출력 함수
/// </summary>
/// <param name="루트 노드"></param>
void BinarySearchTree::Print(Node* node)
{
// 중위 순회
if (!node)
return;
Print(node->LeftChild);
cout << node->Data << " ";
Print(node->RightChild);
}
/// <summary>
/// 루트 노드 반환 함수
/// </summary>
/// <returns>루트 노드</returns>
Node* BinarySearchTree::GetRoot()
{
return mRoot;
}
#include "BinarySearchTree.h"
int main() {
BinarySearchTree bst;
bst.Insert(25);
bst.Insert(40);
bst.Insert(10);
bst.Delete(40);
bst.Insert(50);
bst.Insert(35);
bst.Insert(30);
bst.Delete(10);
bst.Print(bst.GetRoot());
return 0;
}
Output:
25 30 35 50