一、二叉搜索树的最近公共祖先
思路
如果从上往下遍历,发现某结点在p和q的中间(结点的左子树有p/q,右子树有q/p),那么此结点一定是p和q的最近公共祖先,因为不管从结点向左左或者向右遍历,都会错过成为p或q的祖先
代码实现
//递归法
class Solution {
private:
TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q){
if(cur == NULL) return cur;
if(cur->val > p->val && cur->val > q->val) {
TreeNode* left = traversal(cur->left, p, q);
if(left != NULL) {
return left;
}
}
if(cur->val < p->val && cur->val < q->val) {
TreeNode* right = traversal(cur->right, p, q);
if(right != NULL) {
return right;
}
}
return cur;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root, p, q);
}
};
//迭代法
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while(root){
if(root->val > p->val && root->val > q->val) {
root = root->left;
} else if(root->val < p->val && root->val < q->val) {
root = root->right;
} else return root;
}
return NULL;
}
};
二、二叉搜索树的插入操作
思路
新插入的结点在对应的叶子结点插入
当遍历结点为空时,就找到了插入结点的位置,如果当前遍历结点的值大于val,插入结点到当前节点的左子树中,如果当前遍历结点的值小于val,插入节点到当前节点的右子树中。
代码实现
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root == NULL) {
TreeNode* node = new TreeNode(val);
return node; // 把添加结点返回给上一层,就完成了父子结点的赋值操作了
}
if(root->val > val) root->left = insertIntoBST(root->left, val);
if(root->val < val) root->right = insertIntoBST(root->right, val);
return root;
}
};
三、删除二叉搜索树中的结点
思路
先找到删除结点,然后删除结点
1.没找到要删除的结点
2.找到了要删除的结点:
叶子结点(左为空,右为空):直接删除结点,返回NULL为根节点
左不空右为空:删除结点,左孩子补位,返回左孩子为根节点
左为空右不空:删除结点,右孩子补位,返回右孩子为根节点
左不空右不为空:将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
代码实现
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root == nullptr) return root;
if(root->val == key) {
if(root->left == nullptr && root->right == nullptr) {
delete root;
return nullptr;
}
else if(root->left == nullptr) { // 左为空,右不为空
auto retNode = root->right;
delete root;
return retNode;
}
else if(root->right == nullptr) { // 右为空,左不为空
auto retNode = root->left;
delete root;
return retNode;
}
else{ //左右孩子都不为空
TreeNode* cur= root->right;
while(cur->left != nullptr) {
cur = cur->left;
}
cur->left = root->left; //要删除的结点的左子树放在cur的左孩子的位置
TreeNode* tmp = root;
root = root->right; // root的右孩子作为新的root
delete tmp;
return root;
}
}//把新的结点返回给上一层
if(root->val > key) root->left = deleteNode(root->left, key);
if(root->val < key) root->right = deleteNode(root->right, key);
return root;
}
};