【题目】给定一个二叉搜索树的头节点 head 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
【要求】算法时间复杂度为 O ( h ) O(h) O(h),h 为树的高度。
【解题说明】
- 若该节点不存在,则直接返回NULL
- 若该节点存在
- 若该节点左右子树都为空,则直接删除该节点;
- 若该节点的左子树存在,右子树为空,则删除节点,左子树补位,返回左子树为根节点
- 若该节点的右子树存在,左子树为空,则删除节点,右子树补位,返回右子树为根节点
- 若该节点的左右子树都不为空,则将删除节点的左子树头结点放到删除节点的右子树的最左面节点的左子树上,返回删除节点右子树为新的根节点
【C++】
TreeNode* deleteBSTNode(TreeNode* node,int key){
/*没有找到该节点*/
if(node == NULL)
return node;
/*找到该节点*/
if(node->value == key){
/*左右子树都为空,直接删除节点*/
if(node->left == NULL && node->right == NULL){
delete node;
return NULL;
}
/*左子树为空,右子树不为空*/
else if(node->left == NULL){
TreeNode* res = node->right;
delete node;
return res;
}
/*左子树不为空,右子树为空*/
else if(node->right == NULL){
auto res = node->left;
delete node;
return res;
}
/*左右孩子都不为空*/
else{
/*找到该节点右子树上的最左节点*/
TreeNode* cur = node->right;
while(cur->left != NULL){
cur = cur->left;
}
cur->left = node->left;//把要删除的节点的左子树放在该节点右子树上最左子树的位置;
TreeNode* tmp = node;//保存一下要删除的节点
node = node->right;
delete tmp;
return node;
}
}
/*把新的节点返回给上一层,上一层就要用 root->left 或者 root->right接住*/
if(node->value > key)
node->left = deleteBSTNode(node->left,key);
if(node->value < key)
node->right = deleteBSTNode(node->right,key);
return node;
}
【测试】
根据有序数组生成二叉搜索树
#include <iostream>
#include <vector>
using namespace std;
/*树的节点*/
struct TreeNode{
int value;
TreeNode* left;
TreeNode* right;
TreeNode(int val):value(val),left(NULL),right(NULL){}
};
/*根据有序数组生成二叉搜索树*/
TreeNode* generate(vector<int>& sortVec,int start,int end){
if(start > end) return NULL;
int mid = start + (end - start)/2;
TreeNode* head = new TreeNode(sortVec[mid]);
head->left = generate(sortVec,start,mid - 1);
head->right = generate(sortVec,mid + 1,end);
return head;
}
TreeNode* generateBST(vector<int>& sortVec){
return generate(sortVec,0,sortVec.size() - 1);
}
/
/*中序遍历*/
void inOrder(TreeNode* head){
if(head == NULL)
return;
inOrder(head->left);
cout << head->value <<" ";
inOrder(head->right);
}
/*删除值为key的节点*/
TreeNode* deleteBSTNode(TreeNode* node,int key){
/*没有找到该节点*/
if(node == NULL)
return node;
/*找到该节点*/
if(node->value == key){
/*左右子树都为空,直接删除节点*/
if(node->left == NULL && node->right == NULL){
delete node;
return NULL;
}
/*左子树为空,右子树不为空*/
else if(node->left == NULL){
TreeNode* res = node->right;
delete node;
return res;
}
/*左子树不为空,右子树为空*/
else if(node->right == NULL){
auto res = node->left;
delete node;
return res;
}
/*左右孩子都不为空*/
else{
/*找到该节点右子树上的最左节点*/
TreeNode* cur = node->right;
while(cur->left != NULL){
cur = cur->left;
}
cur->left = node->left;//把要删除的节点的左子树放在该节点右子树上最左子树的位置;
TreeNode* tmp = node;//保存一下要删除的节点
node = node->right;
delete tmp;
return node;
}
}
/*把新的节点返回给上一层,上一层就要用 root->left 或者 root->right接住*/
if(node->value > key)
node->left = deleteBSTNode(node->left,key);
if(node->value < key)
node->right = deleteBSTNode(node->right,key);
return node;
}
int main(){
//根据有序数组生成二叉搜索树并中序遍历
vector<int> a = {1,2,3,4,5,6,7,8,9};
TreeNode* head = generateBST(a);
inOrder(head);
cout << endl;
//删除节点并中序遍历
TreeNode* cur = deleteBSTNode(head,5);
inOrder(cur);
cout << endl;
return 0;
}