二叉排序树(二叉搜索树)的基础知识在之前的文章中有详细介绍,包括概念、插入、删除等基本操作,并进行了代码演示。
AVL树作为一种特殊的二叉排序树,对树高做了限制,在之前的文章中也有介绍,包括基本概念,性质,插入与删除过程中出现失衡后如何调整。并进行了代码演示。
题目链接
题目解析:如果所求节点的左右子树都不为0, 则直接寻找该节点右子树的最大值即可(参考之前二叉搜索树中的基本知识介绍中的代码介绍)。但是本题中的节点可能没有右子树,后继节点可能是当前节点的根节点。所以不妨直接用中序遍历的方法,记录上一个遍历的节点,上一个遍历的节点等于所求节点时再返回当前遍历到的节点。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode *last_node; //遍历的上一个节点
TreeNode* inorder(TreeNode *root, TreeNode *p) {
if (root == nullptr) return nullptr;
TreeNode *node;
if (node = inorder(root->left, p)) return node;
if (last_node == p) {
return root;
}
last_node = root;
if (node = inorder(root->right, p)) return node;
return nullptr;
}
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (root == nullptr) return nullptr;
return inorder(root, p); //中序遍历
}
};
总结:结构化遍历,注意if (node = inorder(root->left, p))
是必要的,因为可能会在左子树中找到了目标节点,那直接返回之前的结果即可。
题目链接
题目解析:参考之前介绍过的二叉搜索树基础知识中的代码演示,代码可直接复用。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode *predecessor(TreeNode *root) {
TreeNode *node = root->left;
while (node->right) node = node->right;
return node;
}
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr) return root;
if (key < root->val) root->left = deleteNode(root->left, key);
else if (key > root->val) root->right = deleteNode(root->right, key);
else {
if (root->left == nullptr || root->right == nullptr) {
TreeNode *node = root->left == nullptr ? root->right : root->left;
delete root;
return node;
}else {
TreeNode *node = predecessor(root);
root->val = node->val;
root->left = deleteNode(root->left, node->val);
}
}
return root;
}
};
题目链接
题目分析:一种做法是顺序遍历二叉搜索树,然后按照平衡二叉树的插入方法,结合各种左旋,右旋操作重新构造一颗平衡二叉树。
但是也可以换一个思路,将二叉搜索树看成一个从小到大排列的顺序结构,根节点取中间那个位置,左右子树分别取两边,递归的进行构建二叉树,最终一定是平衡的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void getNodes(TreeNode *root, vector<TreeNode *> &nodes) {
if (root == nullptr) return;
getNodes(root->left, nodes);
nodes.push_back(root);
getNodes(root->right, nodes);
}
TreeNode *build_tree(vector<TreeNode *> &nodes, int l, int r) {
if (l > r) return nullptr;
int mid = (l + r) >> 1;
TreeNode *root = nodes[mid];
root->left = build_tree(nodes, l, mid - 1);
root->right = build_tree(nodes, mid + 1, r);
return root;
}
TreeNode* balanceBST(TreeNode* root) {
vector<TreeNode *> nodes;
getNodes(root, nodes); //将二叉树的节点从小到大才能到nodes中
return build_tree(nodes, 0, nodes.size() - 1); //根据顺序结构nodes构造一个平衡的二叉树
}
};
总结:将二叉搜索树看成右小到大排列的顺序结构。