Binary Search Tree(BST)
創作人:ZJUT_YC
測試代碼還沒有加上,後續補齊。
代碼實現
#pragma once
#include <iostream>
using namespace std;
template<class T>
class BST
{
private:
class Node {
T m_data;
Node* m_left;
Node* m_right;
};
Node* m_root;
public:
bool isEmpty()const;
bool searchRecursive(const T& item);// 查找某個元素是否在樹中(遞歸版本)
bool searchNonRecursive(const T& item); // 查找某個元素是否在樹中(非遞歸版本)
void insert(const T& item);// 將元素插入到二叉樹中
void remove(const T& item);// 將元素從二叉樹中刪除
void inOrder(ostream& os);//遍歷樹的方式:中序遍歷
void leftOrder(ostream& os);//遍歷樹的方式:前序遍歷
void rightOrder(ostream& os);//遍歷樹的方式:後續遍歷
private:
bool searchAux(BST<T>::Node* subRoot,const T& item)const; // 查找輔助函數
void inOrderAux(ostream& os, BST<T>::Node* subRoot)const; // 中序遍歷Aux
void leftOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 前序遍歷Aux
void rightOrderAux(ostream& os, BST<T>::Node* subRoot)const;// 後序遍歷Aux
};
template<class T>
inline bool BST<T>::isEmpty() const
{
return m_root==nullptr;
}
template<class T>
inline bool BST<T>::searchRecursive(const T& item)
{
return searchAux(m_root,item);
}
template<class T>
inline bool BST<T>::searchNonRecursive(const T& item)
{
BST<T>::Node* localptr = m_root;
while (nullptr != localptr) {
if (item < localptr->m_data) {
localptr = localptr->m_left;
}
else if (item > localptr->m_data) {
localptr = localptr->m_right;
}
else {
return true;
}
}
return false;
}
// 二叉樹的插入
template<class T>
inline void BST<T>::insert(const T& item)
{
BST<T>::Node* ptr = m_root;
BST<T>::Node* parent=nullptr;
bool found = false;
while (!found && ptr!=nullptr) {
parent = ptr;
if (item < ptr->m_data)
ptr = ptr->left;
else if(item > ptr->right)
ptr = ptr->right;
else
found = true;
}//1. 先判斷元素item在不在二叉樹中
// 2. 元素在樹中與否執行相應的操作
if (found)// 2.1 元素在樹中
std::cout << "item" << item << " has already exist!\n";
else {
// 2.2 元素不在二叉樹中,則插入元素
// 插入時區分是否爲空樹
BST<T>::Node* newNode = new BST<T>::Node(item);
if (parent == nullptr) //一顆空的樹
m_root = newNode;
if (item<parent->m_data)
{
parent->left = item;
}
else
{
parent->right = item;
}
}
}
template<class T>
inline void BST<T>::remove(const T& item)
{
BST<T>::Node* localptr = m_root;
BST<T>::Node* parent_of_localptr = nullptr;
bool leftNode = true;
while (nullptr != localptr) {
parent_of_localptr = localptr; // localptr的父節點
if (item < localptr->m_data) {
localptr = localptr->m_left;
leftNode = true;
}
else if(item>localptr->m_data){
localptr = localptr->m_right;
leftNode = false;
}
else {
break; // 此時localptr保存的是item所在元素的值
}
}
if (nullptr == localptr) {
return; // 表示沒有這個元素
}
else { // 在BST中找到元素item
// 分情況討論
// 1.localptr指向的節點是葉子節點
if (localptr->m_left == nullptr && localptr->m_right == nullptr) {
if (leftNode) {
parent_of_localptr->m_left = nullptr;
delete localptr; // 將空間釋放,當然也可以將參數放在函數的參數列表中,由外層進行釋放
}
else {
parent_of_localptr->m_right = nullptr;
delete localptr;
}
}
// 2.1 localptr指向的節點只有一個子節點,且爲右子節點
if (localptr->m_left == nullptr && localptr->m_right != nullptr) {
if (leftNode) { // localptr是parent的左子節點
parent_of_localptr->m_left = localptr->m_right;
}
else
{
parent_of_localptr->m_right = localptr->m_right;
}
// 將待刪除節點和其子節點解綁,回收內存
localptr->m_right = nullptr;
delete localptr; //想象一下刪除的過程
}
// 2.2 localptr指向的節點只有一個子節點,且爲左子節點
if (localptr->m_left != nullptr && localptr->m_right == nullptr) {
if (leftNode)
parent_of_localptr->m_left = localptr->m_left;
else
parent_of_localptr->m_right = localptr->m_left;
localptr->m_left = nullptr;
delete localptr;
}
// 3.localptr指向的節點有兩個子節點
if (localptr->m_left!=nullptr && localptr->m_right!=nullptr) {
BST<T>::Node* ptr = localptr->m_right;
BST<T>::Node* ptr_parent = localptr;
bool noLeftNodeOfLocalptrRight = true;
while (nullptr != ptr->m_left) {
noLeftNodeOfLocalptrRight = false;
ptr_parent = ptr;
ptr = ptr->m_left;
}
// 待刪除節點的右子節點沒有左子節點,即localptr->m_right->left=nullptr
if (noLeftNodeOfLocalptrRight) { // localptr->m_right沒有左子樹
localptr->m_right->left = localptr->m_left;
localptr->m_leftptr=localptr->m_right = nullptr;
delete localptr;
}
else { // localptr->m_right有左子節點,成功到達其左子樹,ptr表示後驅節點,parent是ptr的父節點
localptr->m_data = ptr->m_data; // 待刪除節點不需要刪除,只要將其值改爲其後驅節點的值即可
// ptr存在右子節點
if (ptr->m_right != nullptr) { // 後驅節點沒有左子節點:由它的定義決定的
ptr_parent->m_left = ptr->m_right;
ptr->m_right = nullptr; //將後驅節點和它的右子節點解綁
delete ptr;
}
else {//ptr不存在右子節點
ptr_parent->m_left = nullptr;
delete ptr;
}
}
}
}
}
template<class T>
inline void BST<T>::inOrder(ostream& os)
{
inOrderAux(os, m_root);
}
template<class T>
inline void BST<T>::leftOrder(ostream& os)
{
leftOrderAux(os, m_root);
}
template<class T>
inline void BST<T>::rightOrder(ostream& os)
{
rightOrderAux(os, m_root);
}
template<class T>
inline bool BST<T>::searchAux(BST<T>::Node* subRoot, const T& item) const
{
if (subRoot == nullptr) return false;
if (subRoot != nullptr) {
if (item > subRoot->m_data) {
searchAux(subRoot->m_right, item);
}
else if (item < subRoot->m_data) {
searchAux(subRoot->m_left, item);
}
else {
return true;
}
}
}
// 中序遍歷Aux
template<class T>
inline void BST<T>::inOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
if (subRoot != nullptr) {
inOrderAux(os, subRoot->left);
os << subRoot->m_data << " ";
inOrderAux(os, subRoot->right);
}
}
//前序遍歷Aux
template<class T>
inline void BST<T>::leftOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
if (subRoot != nullptr) {
std::cout << subRoot->data;
leftOrderAux(os, subRoot->left);
leftOrderAux(os, subRoot->right);
}
}
//後序遍歷Aux
template<class T>
inline void BST<T>::rightOrderAux(ostream& os, BST<T>::Node* subRoot) const
{
if (subRoot != nullptr) {
rightOrderAux(os, subRoot->left);
rightOrderAux(os, subRoot->right);
std::cout << subRoot->m_data << " ";
}
}