C++实现BST(二叉搜索树)的构建与增删查
BST的查询:
这里给出的是递归的写法(在树和链表中递归写法很常见也很容易理解,这里就不多赘述)
TreeNode* BST::BSTsearch(TreeNode* node , int val){
if(!node){return nullptr;}
if(node->val == val){
return node;
}
return node->val >val ? BSTsearch(node->left, val) : BSTsearch(node->right, val);
}
BST的插入:
由于要插入的节点不存在,所以需要使用上一级的节点,将新的节点接入即可。
bool BST::BSTinsert(TreeNode* node , int val){
TreeNode* next = node;
TreeNode* newnode =new TreeNode(val);
while(next){
if(val<next->val){
if(!next->left){
next->left = newnode;
return true;
}else{
next = next->left;
}
}else if(val>next->val){
if(!next->right){
next->right = newnode;
return true;
}else{
next = next->right;
}
}else{
break;
}
}
return false;
}
BST的删除:
删除节点比较复杂,分为三种情况:
节点的左右节点都为空:
直接删除即可,使父节点指向NULL
节点的左右节点有一个为空:
直接删除即可,使父节点指向节点不为空的那个节点
节点的左右节点都不为空:
找到中序遍历顺序下该节点的下一节点,用该节点来替代这个节点的位置,同时要注意好替代前后的树的结构的保持,建议画图辅助理解。
bool BST::BSTdelete(TreeNode* node , int val){
TreeNode* pre = new TreeNode(INT_MIN);
pre->left = node;
TreeNode* record = pre; // 使用record来记录,使record->left指向root,来简化删除root节点的问题
TreeNode* cur = node;
while(cur){
if(cur->val == val){
TreeNode* curL = cur->left;
TreeNode* curR = cur->right;
bool isleft = (pre->left==cur);
if(!curL&&!curR){// 叶子节点的情况
if(isleft){
pre->left = nullptr;
}else{
pre->right = nullptr;
}
}
if(!curL){ //只有右子树的情况
if(isleft){
pre->left = cur->right;
}else{
pre->right = cur->right;
}
delete cur;
}
if(!curR){ // 只有左子树的情况
if(isleft){
pre->left = cur->left;
}else{
pre->right = cur->left;
}
delete cur;
}
//左右子树都有的情况
TreeNode* next = curR;
while(next->left){
cur=next;
next=next->left;
}
if(next==curR){//CUrR没有左节点的情况
if(isleft){
pre->left = next;
}else{
pre->right = next;
}
curR->left = curL;
delete cur;
}else{//curR有左节点的情况
if(isleft){
pre->left = next;
}else{
pre->right = next;
}
next->left = curL;
cur->left = next->right;
next->right = curR;
}
root = record->left;
delete pre;
return true;
}else if(cur->val<val){
pre=cur;
cur=cur->right;
}else{
pre=cur;
cur=cur->left;
}
}
return false;
}
代码实现以及输出结果:
#include<bits/stdc++.h>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr){}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class BST{
private:
TreeNode* root;
TreeNode* BSTsearch(TreeNode* node, int val);
bool BSTinsert(TreeNode* node ,int val);
void midorder(TreeNode* node){
if(node){
midorder(node->left);
cout<<node->val<<" ";
midorder(node->right);
}
}
void preorder(TreeNode* node){
if(node){
cout<<node->val<<" ";
preorder(node->left);
preorder(node->right);
}
}
bool BSTdelete(TreeNode* node, int val);
public:
BST():root(nullptr){};
BST(const TreeNode &rhs) : root(nullptr){};
void Create(string input){
//getline(cin,input);
istringstream is(input);
string ans;
while(is>>ans){
int val = atoi(ans.c_str());
if(root==nullptr){
root=new TreeNode(val);
}else{
BSTinsert(root,val);
}
}
}
void Search(int val){
if(BSTsearch(this->root,val)!=nullptr){
cout<<"success"<<endl;
}else{
cout<<"fail"<<endl;
}
}
void Insert(int val){
if(BSTinsert(root,val)){
cout<< "insert "<<val <<" success"<<endl;
}else{
cout<<"fail"<<endl;
}
}
void Delete(int val){
if(BSTdelete(root,val)){
cout<<"success"<<endl;
}else{
cout<<"fail"<<endl;
}
}
void midvisit(){
midorder(root);
cout<<endl;
}
void previsit(){
preorder(root);
cout<<endl;
}
};
TreeNode* BST::BSTsearch(TreeNode* node , int val){
if(!node){return nullptr;}
if(node->val == val){
return node;
}
return node->val >val ? BSTsearch(node->left, val) : BSTsearch(node->right, val);
}
bool BST::BSTinsert(TreeNode* node , int val){
TreeNode* next = node;
TreeNode* newnode =new TreeNode(val);
while(next){
if(val<next->val){
if(!next->left){
next->left = newnode;
return true;
}else{
next = next->left;
}
}else if(val>next->val){
if(!next->right){
next->right = newnode;
return true;
}else{
next = next->right;
}
}else{
break;
}
}
return false;
}
bool BST::BSTdelete(TreeNode* node , int val){
TreeNode* pre = new TreeNode(INT_MIN);
pre->left = node;
TreeNode* record = pre;
TreeNode* cur = node;
while(cur){
if(cur->val == val){
TreeNode* curL = cur->left;
TreeNode* curR = cur->right;
bool isleft = (pre->left==cur);
if(!curL&&!curR){// 叶子节点的情况
if(isleft){
pre->left = nullptr;
}else{
pre->right = nullptr;
}
}
if(!curL){ //只有右子树的情况
if(isleft){
pre->left = cur->right;
}else{
pre->right = cur->right;
}
delete cur;
}
if(!curR){ // 只有左子树的情况
if(isleft){
pre->left = cur->left;
}else{
pre->right = cur->left;
}
delete cur;
}
//左右子树都有的情况
TreeNode* next = curR;
while(next->left){
cur=next;
next=next->left;
}
if(next==curR){
if(isleft){
pre->left = next;
}else{
pre->right = next;
}
curR->left = curL;
delete cur;
}else{
if(isleft){
pre->left = next;
}else{
pre->right = next;
}
next->left = curL;
cur->left = next->right;
next->right = curR;
}
root = record->left;
return true;
}else if(cur->val<val){
pre=cur;
cur=cur->right;
}else{
pre=cur;
cur=cur->left;
}
}
return false;
}
int main(){
BST test;
test.Create("12 16 9 18 7 10 13 1 2 8 6");
test.midvisit();
test.previsit();
test.Insert(11);
test.midvisit();
test.previsit();
test.Delete(12);
test.midvisit();
test.previsit();
}