CH 08 Binary Search Tree
Tree
Tree
- cicle이 없는 관계
- 계층적인 구조
- Root Node: 제일 위에 있는 노드, 부모 노드가 없는 노드
- Leaf Node: 제일 아래 있는 노드, 자식 노드가 없는 노드
- tree의 단계를 내려갈 때마다 level 증가
- tree의 일부분을 잘라내도 subtree 형성
- 실제 자료 구조는 root 하나만 존재하고 tree의 모습은 관념적인 개념
Binary Tree
- parent node: 바로 위의 상위 노드
- child node: 바로 밑의 하위 노드
- parent는 여러 개의 child를 가지는 게 가능하지만, child는 여러 개의 parent를 가질 수 없음
- 하나의 노드가 최대 두 개까지의 child node를 가지는 tree
- path: 특정 노드로 가기 위해 거쳐 가는 경로
- tree에선 path가 unique
- ancestor node: 자신보다 위에 있는 모든 상위 노드
- descendant node: 자신보다 밑에 있는 모든 하위 노드
- height: level의 number
Full Tree
- 모든 노드들이 2개의 child node를 갖춘 tree
- leaf node가 모두 같은 level에 존재
- non-leaf node는 모두 child node를 두 개씩 가짐
- level이 h인 full tree는 총 2^h -1 개의 노드를 가짐
- 노드 수가 n개인 tree의 level
- 모든 노드가 선형으로 이루어져 있을 때: n
- full tree일 때: log_2 (n + 1)
Complete Tree
- Full Tree는 Complete Tree의 한 종류
- left는 채워져 있지만 right가 없는 형태
Binary Search Tree (Recursive)
Binary Search Tree
- 현재값보다 작은 값은 왼쪽 노드에, 큰 값은 오른쪽 노드에 위치하는 binary tree
- item끼리 크다 작다는 개념 필요
- item은 서로 다름
Tree.h
#include <string>
#include <fstream>
#include "QueType.h"
typedef char ItemType;
struct TreeNode;
enum OrderType {PRE_ORDER, IN_ORDER, POST_ORDER};
class TreeType {
public:
TreeType();
~TreeType();
TreeType(const TreeType& originalTree);
void MakeEmpty();
void operator=(const TreeType& originalTree);
bool IsEmpty() const;
bool IsFull() const;
int LengthIs() const;
void RetrieveItem(ItemType& item, bool& found);
void InsertItem(ItemType item);
void DeleteItem(ItemType item);
void ResetTree(OrderType order);
void GetNextItem (ItemType& item, OrderType order, bool& finished);
void Print(std::ofstream& outFile) const;
private:
TreeNode* root;
QueType preQue;
QueType inQue;
QueType postQue;
};
Construtor
# 기본 생성자
TreeType::TreeType()
{
root = NULL;
}
# 입력 parameter로 tree가 주어졌을 때 생성자
TreeType::TreeType(const TreeType& originalTree)
{
CopyTree(root, originalTree.root);
}
Destructor
- 입력 paramter가 NULL이 아니라면
- 자기 자신 노드를 먼저 삭제하고 left, right 타고 내려가면서 삭제
- &로 전달되어 노드끼리 이어 주지 않아도 됨
void Destroy(TreeNode*& tree)
{
if (tree != NULL)
{
Destroy(tree->left);
Destroy(tree->right);
delete tree;
}
}
TreeType::~TreeType()
{
Destroy(root);
}
MakeEmpty
void TreeType::MakeEmpty()
{
Destroy(root);
root = NULL;
}
Copy Constructor
- Copy Constructor
- 자기 자신을 복사하는 경우엔 무시
- A = B 에서 B가 originalTree
- originalTree가 root와 다른 경우는 현재 tree 모두 삭제한 뒤 복사
- CopyTree
- A = B에서 B가 empty tree라면 NULL 반환
- 그렇지 않다면 root부터 시작해서 타고 내려가면서 노드 생성 후 복사
- &로 전달하기 때문에 노드는 알아서 연결됨
void CopyTree(TreeNode*& copy, const TreeNode* originalTree);
void TreeType::operator=(const TreeType& originalTree)
{
if (&originalTree == this)
return; // Ignore assigning self to self
Destroy(root); // Deallocate existing tree nodes
CopyTree(root, originalTree.root);
}
void CopyTree(TreeNode*& copy, const TreeNode* originalTree)
{
if (originalTree == NULL)
copy = NULL;
else
{
copy = new TreeNode;
copy->info = originalTree->info;
CopyTree(copy->left, originalTree->left);
CopyTree(copy->right, originalTree->right);
}
}
IsEmpty
bool TreeType::IsEmpty() const
{
return root == NULL;
}
IsFull
bool TreeType::IsFull() const
{
TreeNode* location;
try
{
location = new TreeNode;
delete location;
return false;
}
catch(std::bad_alloc exception)
{
return true;
}
}
LengthIs
- 현재 자기 노드 기준으로 자신의 노드 수 1 + 왼쪽 tree 노드 수 + 오른쪽 tree 노드 수
int TreeType::LengthIs() const
{
return CountNodes(root);
}
int CountNodes(TreeNode* tree)
{
if (tree == NULL)
return 0;
else
return CountNodes(tree->left) + CountNodes(tree->right) + 1;
}
RetrieveItem
- 입력받은 노드가 NULL 이면 찾지 못한 상태이므로 false
- item이 입력받은 노드값보다 작으면 item은 left tree에 존재하기 때문에 left tree 탐색
- item이 입력받은 노드값보다 크면 item은 right tree에 존재하기 때문에 right tree 탐색
- item이 입력받은 노드값보다 작지도 크지도 않고 같으면 item을 찾은 것이므로 true
void Retrieve(TreeNode* tree, ItemType& item, bool& found);
void TreeType::RetrieveItem(ItemType& item, bool& found)
{
Retrieve(root, item, found);
}
void Retrieve(TreeNode* tree, ItemType& item, bool& found)
{
if (tree == NULL)
found = false; // item is not found.
else if (item < tree->info)
Retrieve(tree->left, item, found); // Search left subtree.
else if (item > tree->info)
Retrieve(tree->right, item, found);// Search right subtree.
else
{
item = tree->info; // item is found.
found = true;
}
}
InsertItem method
- 새로 넣으려는 newitem을 root부터 시작해서 비교
- newitem이 더 크면 오른쪽으로 타고 내려가서 비교
- newitem이 더 작으면 왼쪽으로 타고 내려가서 비교
- 타고타고 내려가다 더 갈 노드가 없을 때 그 자리에 insert
- insert 순서에 따라 tree의 모양이 바뀜
- 시간복잡도: O(logN)
- insert 에서는 tree를 &로 전달해 주기 때문에 pointer끼리 이어 주지 않아도 자동으로 이어짐
void Insert(TreeNode*& tree, ItemType item);
void TreeType::InsertItem(ItemType item)
{
Insert(root, item);
}
void Insert(TreeNode*& tree, ItemType item)
{
if (tree == NULL)
{// Insertion place found.
tree = new TreeNode;
tree->right = NULL;
tree->left = NULL;
tree->info = item;
}
else if (item < tree->info)
Insert(tree->left, item); // Insert in left subtree.
else
Insert(tree->right, item); // Insert in right subtree.
}
DeleteItem
-
child node를 지우는 경우
- 해당 노드만 삭제
-
하나의 child node를 가지고 있는 node를 지우는 경우
- 해당 노드를 삭제
- 해당 노드의 자리는 child node로 대치
-
두 개의 child node를 가지고 있는 node를 지우는 경우
- left tree의 최댓값이나 right tree의 최소값이 삭제된 item 자리 대신
- 노드의 위치를 바꾸고 나서도 delete 상황 점검 필요
- left tree의 최댓값이나 right tree의 최소값이 삭제된 item 자리 대신
-
DeleteItem Method 연습
-
Delete
- item이 tree의 값보다 작으면 left tree 검색하도록 함
- item이 tree의 값보다 크면 right tree 검색하도록 함
- item이 tree값과 일치하면 (삭제할 item을 찾으면) DeleteNode 실행
-
DeleteNode
- tempPtr에 삭제해야 할 item 위치 저장
- left tree가 NULL이면 (right child만 존재) item 위치에 right child 대치
- right tree가 NULL이면 (left child만 존재) item 위치에 left child 대치
- left, right child 모두 존재하면 GetPrecessor에 left tree를 넣고 left tree의 most right node를 data에 반환
- item 자리에 data를 놓고 item에 대해 다시 Delete 실시
- item과 data가 뒤바뀐 tree에 대해서도 delete 검사
- GetPrecessor에 right tree를 넣고 right tree의 most left node를 반환하는 방식으로 변환 가능
- item 자리에 data를 놓고 item에 대해 다시 Delete 실시
void DeleteNode(TreeNode*& tree);
void Delete(TreeNode*& tree, ItemType item);
void GetPredecessor(TreeNode* tree, ItemType& data);
void TreeType::DeleteItem(ItemType item)
{
Delete(root, item);
}
void Delete(TreeNode*& tree, ItemType item)
{
if (item < tree->info)
Delete(tree->left, item); // Look in left subtree.
else if (item > tree->info)
Delete(tree->right, item); // Look in right subtree.
else
DeleteNode(tree); // Node found; call DeleteNode.
}
void DeleteNode(TreeNode*& tree)
{
ItemType data;
TreeNode* tempPtr;
tempPtr = tree;
if (tree->left == NULL)
{
tree = tree->right;
delete tempPtr;
}
else if (tree->right == NULL)
{
tree = tree->left;
delete tempPtr;
}
else
{
GetPredecessor(tree->left, data); // GetPredecessor(tree->right, data);
tree->info = data;
Delete(tree->left, data); // Delete(tree->right, data);
}
}
void GetPredecessor(TreeNode* tree, ItemType& data)
{
while (tree->right != NULL)
tree = tree->right;
data = tree->info;
}
/*
void GetPredecessor(TreeNode* tree, ItemType& data)
{
while (tree->left != NULL)
tree = tree->left;
data = tree->info;
}
*/
ResetTree
- next 개념을 넣기 위해서, 실제 tree를 메모리로 저장하기 위해서는 1차원 배열로 저장
- Tree를 Queue 형태로 저장
- Tree Traversal Method (Tree를 저장하는 순서)
- PreOrder: tree-> left -> right
- InOrder: left -> tree ->right
- PostOrder: left -> right -> tree
- PreOrder: tree-> left -> right
void PreOrder(TreeNode*, QueType&);
void InOrder(TreeNode*, QueType&);
void PostOrder(TreeNode*, QueType&);
void TreeType::ResetTree(OrderType order)
{
switch (order)
{
case PRE_ORDER: PreOrder(root, preQue);
break;
case IN_ORDER: InOrder(root, inQue);
break;
case POST_ORDER: PostOrder(root, postQue);
break;
}
}
void PreOrder(TreeNode* tree, QueType& preQue)
{
if (tree != NULL)
{
preQue.Enqueue(tree->info);
PreOrder(tree->left, preQue);
PreOrder(tree->right, preQue);
}
}
void InOrder(TreeNode* tree, QueType& inQue)
{
if (tree != NULL)
{
InOrder(tree->left, inQue);
inQue.Enqueue(tree->info);
InOrder(tree->right, inQue);
}
}
void PostOrder(TreeNode* tree, QueType& postQue)
{
if (tree != NULL)
{
PostOrder(tree->left, postQue);
PostOrder(tree->right, postQue);
postQue.Enqueue(tree->info);
}
}
GetNextItem
- tree를 reset하면 각각의 queue에 순서 맞춰 저장돼 있음
- queue의 특성상 first in, first out
- Deqeue를 하면 다음으로 입력된 값이 출력
void TreeType::GetNextItem(ItemType& item, OrderType order, bool& finished)
{
finished = false;
switch (order)
{
case PRE_ORDER: preQue.Dequeue(item);
if (preQue.IsEmpty())
finished = true;
break;
case IN_ORDER: inQue.Dequeue(item);
if (inQue.IsEmpty())
finished = true;
break;
case POST_ORDER: postQue.Dequeue(item);
if (postQue.IsEmpty())
finished = true;
break;
}
}
Binary Search Tree (Iterative)
FindeNode
- tree에서 item이 존재하는 노드를 nodePtr에, item이 존재하는 노드의 부모 노드를 parentPtr에 반환하는 함수
- item이 nodePtr보다 작을 때는 nodePtr을 parentPtr로 설정하고 left tree를 따라 내려가 값 비교
- item이 nodePtr보다 클 때는 nodePtr을 parentPtr로 설정하고 right tree를 따라 내려가 값 비교
void FindNode(TreeNode* tree, ItemType item, TreeNode*& nodePtr, TreeNode*& parentPtr)
{
nodePtr = tree;
parentPtr = NULL;
bool found = false;
while (nodePtr != NULL && !found)
{
if (item < nodePtr->info)
{
parentPtr = nodePtr;
nodePtr = nodePtr->left;
}
else if (item > nodePtr->info)
{
parentPtr = nodePtr;
nodePtr = nodePtr->right;
}
else
found = true;
}
}
InsertItem
- FindNode 함수를 통해 item을 탐색하면 nodePtr은 NULL, parentPtr은 newNode의 parent node를 가리키게 됨
- InsertItem(13) 실행
- FindNode의 첫 번째 Iteration 후
- FindNode의 두 번째 Iteration 후
- FindNode 세 번째 Iteration 후 최종 결과
- InsertItem(13) 실행
- parentPtr 값이 NULL인 경우 item이 root
- item이 parentPtr 값보다 큰 경우 right child로 붙임
- item이 parentPtr 값보다 작은 경우 left child로 붙임
void TreeType::InsertItem(ItemType item)
{
TreeNode* newNode;
TreeNode* nodePtr;
TreeNode* parentPtr;
newNode = new TreeNode;
newNode->info = item;
newNode->left = NULL;
newNode->right = NULL;
FindNode(root, item, nodePtr, parentPtr);
if (parentPtr == NULL) // Insert as root.
root = newNode;
else if (item < parentPtr->info)
parentPtr->left = newNode;
else parentPtr->right = newNode;
}
DeleteItem
- Delete는 삭제해야 할 값 위치를 알려 주는 함수
- DeleteNode는 child node 수에 따라 경우를 나눠 노드들을 삭제해 주는 함수
- GetPredecessor는 child가 두 개인 노드를 삭제할 때 left tree의 most right node의 값을 찾아서 반환해 주는 함수
- item을 찾은 위치가 root라면 root만 삭제
- item을 찾은 위치가 parentPtr의 left child라면 left child 삭제
- item을 찾은 위치가 parentPtr의 right child라면 right child 삭제
- DeleteNode parameter로는 nodePtr 금지
- &로 받기 때문에 parentPtr->left, parent->right로 넣어야 노드들이 자연스럽게 연결됨
void GetPredecessor(TreeNode* tree, ItemType& data);
void Delete(TreeNode*& tree, ItemType item);
void DeleteNode(TreeNode*& tree)
{
ItemType data;
TreeNode* tempPtr;
tempPtr = tree;
if (tree->left == NULL)
{
tree = tree->right;
delete tempPtr;
}
else if (tree->right == NULL)
{
tree = tree->left;
delete tempPtr;
}
else
{
GetPredecessor(tree->left, data);
tree->info = data;
Delete(tree->left, data);
}
}
void Delete(TreeNode*& tree, ItemType item)
{
if (item < tree->info)
Delete(tree->left, item); // Look in left subtree.
else if (item > tree->info)
Delete(tree->right, item); // Look in right subtree.
else
DeleteNode(tree); // Node found; call DeleteNode.
}
void GetPredecessor(TreeNode* tree, ItemType& data)
{
while (tree->right != NULL)
tree = tree->right;
data = tree->info;
}
void TreeType::DeleteItem(ItemType item)
{
TreeNode* nodePtr;
TreeNode* parentPtr;
FindNode(root, item, nodePtr, parentPtr);
if (nodePtr == root)
DeleteNode(root);
else
if (parentPtr->left == nodePtr)
DeleteNode(parentPtr->left);
else DeleteNode(parentPtr->right);
}
Plus
Big-O Comparison
Operation | Binary Search Tree | Array-based List | Linked List |
---|---|---|---|
Constructor | O(1) | O(1) | O(1) |
Destructor | O(N) | O(1) | O(N) |
IsFull | O(1) | O(1) | O(1) |
IsEmpty | O(1) | O(1) | O(1) |
RetrieveItem | O(logN) | O(logN) | O(N) |
InsertItem | O(logN) | O(N) | O(N) |
DeleteItem | O(logN) | O(N) | O(N) |
Array Representation
- current node: tree.node[index]
- parent node: tree.node[(index-1) / 2]
- left child node: tree.node[index/2 + 1]
- right child node: tree.node[index/2 + 2]
LAB
PtrToSuccessor
- 트리 내의 가장 작은 키를 가진 노드를 찾고 트리에서 그 노드의 연결을 제거한 뒤 연결이 제거된 노드를 가리키는 포인터를 반환
- Recursive
TreeNode* TreeType::PtrToSuccessor(TreeNode*& tree)
{
if (tree->left != NULL)
PtrToSuccessor(tree->left);
else
{
TreeNode* tempPtr = tree;
tree = tree->right;
return tempPtr;
}
}
- Iterative
TreeNode* TreeType::PtrToSuccessor(TreeNode*& tree)
{
while (tree->left == NULL)
tree = tree->left;
TreeNode* tempPtr = tree;
tree = tree->right;
return tempPtr;
}
isBST
- 해당 tree가 Binary Search Tree가 맞는지 검사하는 함수
- 단순히 현재 노드보다 작은 값은 left, 큰 값은 right에 있는지만 검사해선 안 됨 (아래 예시는 해당 조건을 만족하지만 BST가 아님)
- left tree의 most right node가 left tree의 parent보다 작은지 검사해야 함
- right tree의 most left node가 right tree의 parent보다 큰지 검사해야 함
bool Imp_IsBST(TreeNode* tree, ItemType& min, ItemType& max);
bool TreeType::IsBST()
{
ItemType min, max;
return Imp_IsBST(root, min, max);
}
bool Imp_IsBST(TreeNode* tree, ItemType& min, ItemType& max) {
bool isBST;
if (tree == NULL)
return true;
if (tree->left != NULL) {
char left_max = tree->info;
isBST = Imp_IsBST(tree->left, min, left_max);
if (!isBST || tree->info <= min || left_max > tree->info)
return false;
}
if (tree->right != NULL) {
char right_min = tree->info;
isBST = Imp_IsBST(tree->right, right_min, max);
if (!isBST || tree->info >= max || right_min < tree->info)
return false;
}
min = (tree->left == NULL) ? tree->info : min;
max = (tree->right == NULL) ? tree->info : max;
return true;
}
- Level 1: Level 2의 재귀로 left tree를 보내고 left tree의 parent인 8을 left max로 전달
- Level 2: 전달받은 left max값이 max가 되고 Level 3의 재귀로 left tree 전달 후 left tree의 parent인 3을 left max로 전달
- Level 3: 전달받은 left max값이 max가 되고 Level 4의 재귀로 left tree 전달 후 left tree의 parent인 2를 left_max로 전달
- Level 4: 전달받은 left max 값이 max가 되고 더 이상 재귀가 호출되지 않아 min, max 업데이트 후 true return
- Level 3: parameter로 넣었던 left max가 1로 업데이트 되고 조건식 검사
- Level 3 : min, max 업데이트 후 true 반환
- Level 2: isBST가 true가 되고 parameter로 넣었던 left max가 level 3의 max인 2로 변경
- Left Tree 검사할 때
- max: 현재 노드의 parent node
- left_max: 현재 노드의 left tree의 최대값 (most right node)
- Right Tree 검사할 때
- min: 현재 노드의 parent node
- right_min: 현재 노드의 right tree의 최소값 (most left node)
LeafCount
- BST의 leaf node 수 반환
- tree가 NULL이면 아무것도 아님
- tree의 left, right가 모두 NULL이면 tree는 leaf
- tree의 left, right 중 하나라도 NULL이 아니면 left tree의 leaf + right tree의 leaf 반환
int Imp_LeafCount(TreeNode* tree);
int TreeType::LeafCount()
{
return Imp_LeafCount(root);
}
int Imp_LeafCount(TreeNode* tree)
{
if (tree == NULL)
return 0;
else if (tree->left == NULL && tree->right == NULL)
return 1;
else
return Imp_LeafCount(tree->left) + Imp_LeafCount(tree->right);
}
SingleParentCount
- BST의 노드 중 하나의 child만 가진 노드 수 반환
- tree가 0이면 0 반환
- tree의 left만 NULL이면 자기 자신 (1) + right tree 검사값 반환
- tree의 right만 NULL이면 자기 자신 (1) + left tree 검사값 반환
- tree의 left, right 모두 NULL이 아니면 left tree 검사값 + right tree 검사값 반환
int Imp_SingleParentCount(TreeNode* tree);
int TreeType::SimgleParentCount()
{
return Imp_SingleParentCount(root);
}
int Imp_SingleParentCount(TreeNode* tree)
{
if (tree == NULL)
return 0;
else if (tree->left == NULL && tree->right != NULL)
return 1 + Imp_SingleParentCount(tree->right);
else if (tree->left != NULL && tree->right == NULL)
return 1 + Imp_SingleParentCount(tree->left);
else
return Imp_SingleParentCount(tree->left) + Imp_SingleParentCount(tree->right);
}
PtrToSuccess 이용한 DeleteNode
- PtrToSuccess: 최소값을 갖는 노드 반환해 주는 함수
TreeNode* TreeType::PtrToSuccessor(TreeNode*& tree)
{
if (tree->left != NULL)
PtrToSuccessor_re(tree->left);
else
{
TreeNode* tempPtr = tree;
tree = tree->right;
return tempPtr;
}
}
- DeleteNode 실행 시 left, right child를 모두 다 가지고 있는 경우라면 right tree의 최소값과 값 바꾸기
- PtrToSuccess의 return 값을 tree에 적용
- PtrToSuccess에 넣은 parameter는 최소값 노드의 right sub tree 가리킴
void DeleteNode(TreeNode*& tree)
{
ItemType data;
TreeNode* tempPtr;
tempPtr = tree;
if (tree->left == NULL)
{
tree = tree->right;
delete tempPtr;
}
else if (tree->right == NULL)
{
tree = tree->left;
delete tempPtr;
}
else
{
PtrToSuccess(tree->right, data);
tree->info = data;
Delete(tree->right, data); // Delete predecessor node.
}
}
Ancestor
- 현재 노드를 기준으로 조상 노드 출력
- Recursive
bool Imp_Ancestor_re(TreeNode* tree, ItemType value);
void TreeType::Ancestors_re(ItemType value)
{
Imp_Ancestor_re(root, value);
}
bool Imp_Ancestor_re(TreeNode* tree, ItemType value)
{
bool found = false;
if (tree == NULL)
return false;
if (tree->info == value)
return true;
if (tree->info < value)
{
found = Imp_Ancestor_re(tree->right, value);
}
else
{
found = Imp_Ancestor_re(tree->left, value);
}
if (found)
{
std::cout << tree->info << std::endl;
return found;
}
}
- Iterative
void TreeType::Ancestors_iter(ItemType value)
{
bool found = false;
QueType path;
TreeNode* currentNode = root;
while (!found && currentNode == NULL)
{
if (currentNode->info == value)
found = true;
else
{
path.Enqueue(currentNode->info);
if (value > currentNode->info)
currentNode = currentNode->right;
else
currentNode = currentNode->left;
}
}
if (found)
{
while (!path.IsEmpty())
{
ItemType item;
path.Dequeue(item);
std::cout << item << std::endl;
}
}
}
Smaller
- 트리내에서 Value 보다 작은 값을 갖는 노드의 수를 반환하는 클라이언트 함수
- IN_ORDER로 저장하면 item이 오름차순으로 Queue에 저장됨
- item에 Queue의 요소들을 차례차례 담아 오고, 이 값이 value보다 작다면 count++
- item 값이 value보다 큰 지점에서 finish 값을 바꿔 반복문 종료
int Smaller(TreeType tree, int value)
{
ItemType item;
bool finished = false;
int count = 0;
tree.ResetTree(IN_ORDER); // IN_ORDER는 Sorted 형태로 저장됨
while (!finished)
{
tree.GetNextItem(item, IN_ORDER, finished);
if (item < value)
count++;
else
finished = true;
}
return count;
}
MakeTree
- SortedList를 tree로 만드는 작업
- SortedList 길이만큼 item_info에 값을 받아와서 tree에 Insert
- tree에 넣을 때 중간값인 mid부터 insert
- 첫 번째 값부터 넣으면 깊이가 n인 비효율적 tree 생성
- right tree 생성은 from index를 mid + 1로 전달
- left tree 생성은 to index를 mid - 1로 전달
void AddElement(TreeType& tree, int Array[], int from, int to);
void MakeTree(TreeType& tree, SortedType<int>& list);
void AddElement(TreeType& tree, int Array[], int from, int to) {
int mid;
if (from <= to) {
mid = (from + to) / 2;
tree.InsertItem(Array[mid]);
cout << Array[mid] << endl;
AddElement(tree, Array, mid + 1, to);
AddElement(tree, Array, from, mid - 1);
}
}
void MakeTree(TreeType& tree, SortedType<int>& list) {
int length = list.LengthIs();
int* array = new int[length];
int item_info;
int i;
list.ResetList();
for (i = 0; i < length; i++) {
list.GetNextItem(item_info);
array[i] = item_info;
}
AddElement(tree, array, 0, length - 1);
delete[] array;
}
PP
Recursive Binary Search Tree
class TreeNode:
def __init__(self, info):
self.info = info
self.left = None
self.right = None
class BST():
def __init__(self):
self.root = None
self.order_list = []
def is_empty(self):
return (self.root == None)
def count_nodes(self, tree):
if (tree == None):
return 0
else:
return 1 + self.count_nodes(tree.left) + self.count_nodes(tree.right)
def length_is(self):
return self.count_nodes(self.root)
def insert(self, item):
self.root = self.insert_item(self.root, item)
return self.root is not None
def insert_item(self, node, item):
if node is None:
node = TreeNode(item)
else:
if item <= node.info:
node.left = self.insert_item(node.left, item)
else:
node.right = self.insert_item(node.right, item)
return node
def inorder(self, node):
if(node != None) :
self.inorder(node.left)
self.order_list.append(node.info)
self.inorder(node.right)
def preorder(self, node):
if(node != None):
self.order_list.append(node.info)
self.preorder(node.left)
self.preorder(node.right)
def postorder(self, node):
if(node != None):
self.postorder(node.left)
self.postorder(node.right)
self.order_list.append(node.info)
def delete(self, item):
self.root = self.delete_node(self.root, item)
def delete_node(self, current, item):
if (current == None):
return current
if ( item == current.info):
if(current.left == None and current.right == None):
current = None
elif(current.left == None):
current = current.right
elif(current.right == None):
current = current.left
else:
data = 0
data = self.get_predecessor(data)
current = TreeNode(data)
elif ( item < current.info):
current.left = self.delete_node(current.left, item)
else:
current.right = self.delete_node(current.right, item)
return current
def get_predecessor(tree, data):
while(tree.right != None):
tree = tree.right
data = tree.info
return data
Iterative Binary Search Tree
class NodeType:
def __init__(self, data):
self.info = data
self.left = None
self.right = None
class IterBST():
def __init__(self):
self.root = None
self.order_list = []
def insert(self, data):
newnode = NodeType(data)
parentPtr = self.find(data)
if(parentPtr == None):
self.root = newnode
elif (data < parentPtr.info):
parentPtr.left = newnode
else:
parentPtr.right = newnode
def find(self, key):
nodePtr, parentPtr, found = self.find_node(self.root, key)
return parentPtr
def find_node(self, root, key):
nodePtr = root
parentPtr = None
found = False
while(nodePtr != None and (not found)):
if(key < nodePtr.info):
parentPtr = nodePtr
nodePtr = nodePtr.left
elif (key > nodePtr.info):
parentPtr = nodePtr
nodePtr = nodePtr.right
else:
found = True
return nodePtr, parentPtr, found
def delete(self, key):
self.root = self.delete_node(self.root, key)
def delete_node(self, node, key):
if (node == None):
return node
if (key == node.info):
if(node.left == None and node.right == None):
node = None
elif(node.left == None):
node = node.right
elif(node.right == None):
node = node.left
else:
data = 0
data = self.get_predecessor(data)
node = NodeType(data)
elif (key < node.info):
node.left = self.delete_node(node.left, key)
else:
node.right = self.delete_node(node.right, key)
return node
def inorder(self, node):
if(node != None) :
self.inorder(node.left)
self.order_list.append(node.info)
self.inorder(node.right)
def preorder(self, node):
if(node != None):
self.order_list.append(node.info)
self.preorder(node.left)
self.preorder(node.right)
def postorder(self, node):
if(node != None):
self.postorder(node.left)
self.postorder(node.right)
self.order_list.append(node.info)
def get_predecessor(tree, data):
while(tree.right != None):
tree = tree.right
data = tree.info
return data
Author And Source
이 문제에 관하여(CH 08 Binary Search Tree), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@morion002/CH-08-Binary-Search-Tree저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)