/*
二叉查找树 插入 查找前驱、后继 删除
https://www.cnblogs.com/skywang12345/p/3576373.html*/
#include <iostream>
#include <stack>
using namespace std;
struct BSTNode
{
int val;
BSTNode *left;
BSTNode *right;
BSTNode *parent;
BSTNode(int v, BSTNode *l, BSTNode *r, BSTNode *p) :val(v), left(l), right(r), parent(p) {}
};
/*插入节点node到root指向的二叉查找树中*/
void insert(BSTNode *root, BSTNode *node)
{
if (node == nullptr)
return;
if (root == nullptr)
{
node->parent = nullptr;
root = node;
return;
}
BSTNode *temp = root;
BSTNode *parent = nullptr;//保存待插入节点的父节点
while (temp)
{
parent = temp;
if (node->val > temp->val)
temp = temp->right;
else
temp = temp->left;
}
node->parent = parent;
if (node->val > parent->val)
parent->right = node;
else
parent->left = node;
}
/*二叉查找树中序遍历 升序*/
void inorderprint(BSTNode *root)
{
if (root == nullptr) return;
stack<BSTNode *> s;
BSTNode *curr = root;
while (curr || !s.empty())
{
if (curr)
{
s.push(curr);
curr = curr->left;
}
else
{
cout << s.top()->val << " ";
curr = s.top()->right;
s.pop();
}
}
}
/*查找某个值的节点*/
BSTNode *search(BSTNode *root, int sval)
{
if (root == nullptr) return nullptr;
BSTNode *temp = root;
while (temp)
{
if (temp->val > sval)
temp = temp->left;
else if(temp->val < sval)
temp = temp->right;
else
return temp;
}
return nullptr;
}
/*二叉查找树值最小的节点*/
BSTNode *minkeynode(BSTNode* root)
{
if (!root) return nullptr;
BSTNode *temp = root;
while (temp->left)
{
temp = temp->left;
}
return temp;
}
BSTNode *maxkeynode(BSTNode* root)
{
if (!root) return nullptr;
BSTNode *temp = root;
while (temp->right)
{
temp = temp->right;
}
return temp;
}
/*前驱节点(有无左子)-查找"二叉树中数据值小于该结点"的"最大结点"*/
BSTNode *prenode(BSTNode* root, int val)
{
if (!root) return nullptr;
BSTNode *node = search(root, val);//找到该值的节点
if (!node) return nullptr;
//有左子,则以左子为根的最大节点为当前节点的前驱
if (node->left)
return maxkeynode(node->left);
//无左子:(1)为右子,则其前驱为其父节点;
// (2)为左子,则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
BSTNode *parent = node->parent;
while (parent && parent->left == node)//如果当前节点是最左子,则parent最后是空,返回空是正确的
{
node = parent;
parent = parent->parent;
}
return parent;
}
/*后继节点(有无右子)-查找"二叉树中数据值大于该结点"的"最小结点"。*/
BSTNode *postnode(BSTNode *root, int val)
{
if (!root) return nullptr;
BSTNode *node = search(root, val);
if (!node) return nullptr;
//有右子,后继:右子为根的最小节点(最左节点
if (node->right)
return minkeynode(node->right);
//无右子, 1、为左子,后继是其父;
// 2、为右子,寻找最低父节点,该父节点有左子
BSTNode *parent = node->parent;
while (parent && parent->right == node)
{
node = parent;
parent = parent->parent;
}
return parent;
}
/*删除*/
void transplant(BSTNode *root, BSTNode *oldnode, BSTNode *newnode)
{//new覆盖old,维护new的父节点与new指向关系。newnode可以为空
//parent指向new
if (!oldnode->parent) root = newnode;
else if (oldnode == oldnode->parent->left) oldnode->parent->left = newnode;
else oldnode->parent->right = newnode;
//new指向parent
if (newnode) newnode->parent = oldnode->parent;
}
void removenode(BSTNode *root, int val)
{
if (!root) return;
BSTNode *node = search(root, val);
if (!node) return;
if (!node->left) transplant(root, node, node->right);//1、无左子,不管是否有右子,直接用右子覆盖
else if (!node->right) transplant(root, node, node->left);//2、有左子:2.1、无右子,直接用左子覆盖
else
{//2、有左子:2.2、有右子
BSTNode *nodeSucc = minkeynode(node->right);//node的后继
//2.2.1、待删除node的后继不是其右子,用后继的右子覆盖后继,并让后继接管node的右子树(修node右子和该后继的父子关系)
//之后用该后继覆盖node并接管node的左子
if (nodeSucc->parent != node)
{
transplant(root, nodeSucc, nodeSucc->right);
nodeSucc->right = node->right;//后继接管node的右子树
nodeSucc->right->parent = nodeSucc;
}
//2.2.2、node的后继是其右子(即右子无左子),用后继覆盖node并接管node的左子
transplant(root, node, nodeSucc);
nodeSucc->left = node->left;//接管node的左子
nodeSucc->left->parent = nodeSucc;
}
delete node;
}
int main()
{
BSTNode *root = new BSTNode{ 88,NULL,NULL,NULL };
if (!root)
return -1;
BSTNode *node1 = new BSTNode{ 47,NULL,NULL,NULL };
insert(root, node1);
BSTNode *node2 = new BSTNode{ 98,NULL,NULL,NULL };
insert(root, node2);
BSTNode *node3 = new BSTNode{ 46,NULL,NULL,NULL };
insert(root, node3);
BSTNode *node4 = new BSTNode{ 19,NULL,NULL,NULL };
insert(root, node4);
BSTNode *node5 = new BSTNode{ 55,NULL,NULL,NULL };
insert(root, node5);
BSTNode *node6 = new BSTNode{ 50,NULL,NULL,NULL };
insert(root, node6);
cout << "二叉查找树通过插入构建后的中序遍历结果:";
inorderprint(root);
cout << endl;
cout << "查找19结果:" << search(root, 19) << endl;//没找到返回空
cout << "查找10结果:" << search(root, 10) << endl;
cout << "二叉查找树最小节点值:" << minkeynode(root)->val << endl;
cout << "二叉查找树最大节点值:" << maxkeynode(root)->val << endl;
cout << "查找某个值的前驱节点:" << prenode(root, 50)->val << endl;//无前驱返回nullptr
cout << "查找某个值的后继节点:" << postnode(root, 50)->val << endl;
cout << "删除某个节点后中序遍历结果:";
removenode(root, 19);
inorderprint(root);
cout << endl;
}