#include<iostream>
using namespace std;
typedef struct BSTree
{
int key;
struct BSTree *LChild , *RChild;
}BSTree;
class CBSTree
{
private:
BSTree *root; //二叉排序樹的根節點,可以代表一個樹
bool SearchKey(int key,BSTree **node,BSTree *root,BSTree *Father);
void traverse(BSTree *root2);
bool DeleteKey(int key,BSTree **root);
public:
CBSTree();
~CBSTree();
bool search(int key, BSTree**node,BSTree *Father); //對SearchKey 函數的一個封裝,減少參數
bool InsertKey( int key);
void Traverse(); //對遍歷函數traverse的一個封裝,減少參數
void CreateBSTree(int data[],int length);
void DeleteCBSTree(BSTree **root);
void DeleteOperation(BSTree **node);
bool DeleteKeyEx(int key); // 對DeleteKey的一個封裝減少參數
};
CBSTree::CBSTree()
{
root = NULL; //對樹進行初始化,爲空樹
}
CBSTree::~CBSTree()
{
DeleteCBSTree(&root);
}
bool CBSTree::SearchKey(int key,BSTree **node,BSTree *root,BSTree *Father)
{
if(!root) //如果爲空
{
*node = Father;
return false;
}
else
{
if(key > root->key)
{
Father = root;
return SearchKey( key, node,root->RChild, root);
}
else if(key < root->key)
{
Father = root;
return SearchKey(key , node, root->LChild, root);
}
else
{
*node = root; //把root指針的地址數據傳給node,這樣函數外部node對應的變量就能獲取當前root本身,而不是副本
return true;
}
}
}
void CBSTree::traverse(BSTree *root2)
{
if(root2)
{
traverse(root2->LChild);
cout << root2->key <<" ";
traverse(root2->RChild);
}
}
bool CBSTree::search(int key, BSTree**node,BSTree *Father = NULL)
{
return SearchKey(key,node,root,Father);
}
bool CBSTree::InsertKey( int key)
{
if(!this->root) //先判斷當前root是否爲空,爲空就把root作爲根節點,左右孩子爲空
{
this->root = new BSTree;
this->root->key = key;
this->root->LChild = NULL;
this->root->RChild = NULL;
return true;
}
else //root不爲空
{
BSTree *temp = NULL; //temp保存search到的key對應的節點指針,如果沒有search到則保存沿着路線查找的最後一個節點
if(search(key,&temp))
{
cout << key << "已經存在"<< endl;
return false;
}
else
{
if(key > temp->key)
{
temp->RChild = new BSTree;
temp->RChild->key = key;
temp->RChild->LChild = NULL;
temp->RChild->RChild = NULL;
return true;
}
else
{
temp->LChild = new BSTree;
temp->LChild->key = key;
temp->LChild->LChild = NULL;
temp->LChild->RChild = NULL;
return true;
}
}
}
}
void CBSTree::Traverse() //對遍歷函數traverse的一個封裝,減少參數
{
traverse(root);
}
void CBSTree::CreateBSTree(int data[],int length) //創建二叉排序樹的過程就是把一次次插入新節點的過程
{
for(int i = 0; i < length; i++)
{
InsertKey(data[i]);
}
}
void CBSTree::DeleteCBSTree(BSTree **root) //刪除整個樹
{
if(*root)
{
DeleteCBSTree(&(*root)->LChild);
DeleteCBSTree(&(*root)->RChild);
delete *root;
*root = NULL;
}
}
void CBSTree::DeleteOperation(BSTree **node) //刪除某個指針對應節點的具體操作
{
if(!(*node)->LChild && !(*node)->RChild) //如果該節點沒有左右孩子,則直接刪除,並複製爲空
{
delete(*node); //關鍵點是該函數傳進來的參數*node必須是root這個二叉樹內的真實節點,非拷貝
*node = NULL; //因爲要對root內部的真實節點進行操作
}
else if((*node)->LChild && !(*node)->RChild) //如果只有左孩子
{
BSTree *temp = *node;
(*node) = (*node)->LChild; //則把指向該節點的指針指向節點左孩子
delete temp;
}
else if((*node)->RChild && !(*node)->LChild) //如果只有右孩子,參考上面
{
BSTree *temp = (*node)->RChild;
delete (*node);
(*node) = temp;
}
else //如果左右孩子都有
{
BSTree*temp = (*node)->RChild;
while(temp->LChild->LChild) //尋找*node右子樹下最靠左的葉子節點也就是最小的節點,也就是中序遍歷下*node的後繼,獲取它的父節點
{
temp = temp->LChild; //關鍵點:如果不獲取父節點,而是直接獲取最小節點的話,temp存儲的是該節點的一個拷貝,不能直接進行操作
}
(*node)->key = temp->LChild->key; //通過最小節點的父節點temp指向最小節點這個不是拷貝,而是直接操作了root裏的節點
DeleteOperation(&temp->LChild);
}
}
bool CBSTree::DeleteKey(int key,BSTree **root) //找到要刪除的節點的指針,調用具體操作的函數刪除
{
if(!*root) //如果爲空
{
cout << "未找到" << key << endl;
return false;
}
else
{
if(key > (*root)->key)
{
return DeleteKey( key,&(*root)->RChild);
}
else if(key < (*root)->key)
{
return DeleteKey(key , &(*root)->LChild);
}
else
{
DeleteOperation(&*root);
return true;
}
}
}
bool CBSTree::DeleteKeyEx(int key)
{
return DeleteKey(key,&root);
}
二叉排序樹的創建,插入,遍歷,節點刪除,整個刪除的封裝
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.