typedef Key int; // search key
typedef Data double; // search data
// 원래는 구분이 되어야 좋다
typedefstruct item
{
Key searchKey; // search key
Data searchData; // search data
} Item;
voidBSTInsert(BTreeNode ** pRoot, BSTData data)
{
BTreeNode * pNode = NULL; // parent node
BTreeNode * cNode =*pRoot; // current node
BTreeNode * nNode = NULL; // new node
// 새로운 노드가(새 데이터가 담긴 노드가 추가될 위치를 찾는다.)
while(cNode != NULL)
{
if(data == GetData(cNode))
return; // 데이터의 중복 허용 금지
pNode = cNode; // parent node 백업 -> 자식 노드 확인시 필요
if(GetData(cNode) > data)
cNode = GetLeftSubTree(cNode);
else
cNode = GetRightSubTree(cNode);
// pNode의 자식 노드로 새 노드를 추가
if(pNode != NuLL) // 새 노드가 루트 노드가 아니라면
{
if(data < GetData(pNode))
MakeLeftSubTree(pNode, nNode);
else
MakeRightSubTree(pNode, nNode);
}
else// 새 노드가 루트 노드라면,
{
*pRoot = nNode;
}
}
}
BTreeNode *BSTSearch(BTreeNode * bst, BSTData target)
{
BTreeNode * cNode = bst; // current node
BSTData cd; // current data
while(cNode != NULL) // 삽입 과정을 근거로 탐색 진행
{
cd = GetData(cNode);
if(target == cd)
return cNode; // 탐색 성공시 해당 노드 주소값 반환
elseif(target < cd)
cNode = GetLeftSubTree(cNode);
else
cNode = GetRightSubTree(cNode);
}
return NULL; // 탐색 대상 저장되어있지 않음
}
이진 탐색 트리 삭제 구현
삭제는 해당 노드의 부모 노드의 주소값을 알아야 함
삭제로 빈 자리를 어떻게 채워야 할까?
루트 노드가 루트 노드가 아닌 것처럼 취급할 것 ⇒ 삭제 이전에 노드를 하나 만들어서 root가 서브트리인 것처럼 할 것
삭제할 노드가 단말 노드인 경우
삭제할 노드가 하나의 자식 노드(서브 트리)를 갖는 경우
삭제할 노드가 두 개의 자식 노드(서브 트리)를 갖는 경우
삭제 노드가 단말 노드인 경우
1
2
3
4
5
6
7
8
// dNode와 pNode는 삭제할 노드와 이의 부모 노드를 가리키는 포인터 변수
if(삭제할노드가단말노드이다!)
{
if(GetLeftSubTree(pNode) == dNode) // 삭제할 노드가 왼쪽 자식 노드라면,
RemoveLeftSubTree(pNode); // 왼쪽 자식 노드 트리에서 제거
else// 삭제할 노드가 오른쪽 자식 노드라면,
RemoveRightSubTree(pNode); // 오른쪽 자식 노드 트리에서 제거
}
삭제할 노드가 하나의 자식 노드를 갖는 경우
→ 삭제 후 자식 노드를 가져다 놓는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// dNode와 pNode는 삭제할 노드와 이의 부모 노드를 가리키는 포인터 변수
if(삭제할노드가하나의자식노드를지닌다)
{
BTreeNode * dcNode; // 삭제 대상의 자식 노드를 가리키는 포인터 변수
// 삭제 대상의 자식 노드를 찾는다. 자식노드 백업
if(GetLeftSubTree(dNode) != NULL) // 왼쪽 자식 노드
dcNode = GetLeftSubTree(dNode);
else// 오른쪽 자식 노드
dcNode = GetRightSubTree(dNode);
// 삭제 대상의 부모 노드와 자식 노드를 연결한다
if(GetLeftSubTree(pNode) == dNode) // 삭제 대상이 왼쪽 자식 노드라면,
ChangeLeftSubTree(pNode, dcNode); // 왼쪽 연결
else// 삭제 대상이 오른쪽 자식 노드 이면,
ChangeRightSubTree(pNode, dcNode); // 오른쪽 연결
}
삭제할 노드가 두 개의 자식 노드(서브 트리)를 갖는 경우
삭제 대상을 왼쪽 서브 트리에서 가장 큰 값, 혹은 오른쪽 서브 트리에서 가장 작은 값으로 대체 → 대체하다보면 구조가 바뀜
// dNode와 pNode는 각각 삭제할 노드와 이의 부모 노드를 가리키는 포인터 변수
if(삭제할노드가두개의자식노드를지닌다)
{
BTreeNode * mNode = GetRightSubTree(dNode); // mNode는 대체노드
BTreeNode * mpNode = dNode // mpNode는 대체노드의 부모 노드
....
// 1. 삭제 대상의 대체 노드를 찾는다.
while(GetLeftSubTree(mNode) != NULL)
{
mpNode = mNode;
mNode = GetLeftSubTree(mNode);
}
// 2. 대체할 노드에 저장된 값을 삭제할 노드에 대합니다
SetData(dNode, GetData(mNode));
// 3. 대체할 노드의 부모 노드와 자식 노드를 연결한다.
if(GetLeftSUbTree(mpNode) == mNode) // 대체할 노드가 왼쪽 자식 노드라면
{
// 대체할 노드의 자식 노드를 부모 노드의 왼쪽에 연결
ChangeLeftSubTree(mpNode, GetLeftSubTree(mNode)); // 자식 노드가 있다면 왼쪽 자식노드 이다.
}
else// 대체할 노드가 오른쪽 자식 노드라면
{
// 대체할 노드의 자식 노드를 부모 노드의 오른쪽에 연결
ChangeRightSubTree(mpNode, GetRightSubTree(mNode)); // 자식 노드가 있다면 오른쪽노드 이다.
}
}