二叉排序树基础知识
名称:二叉排序树、二叉搜索树
性质:
1 左子树 < 根节点
2 右子树 > 根节点
用途:解决与排名相关的检索需求
二叉查找树的删除
- 删除叶子节点(出度为0的节点) 直接删除
- 删除出度为1的节点 提升该节点的唯一子树
- 删除出度为2的节点 找到前驱或者后继替换后 转换为度为1的节点问题
struct Node {
Node(int key = 0, Node *left = nullptr, Node *right = nullptr)
: key(key), left(left), right(right) {}
int key;
Node *left, Node *right;
};
Node *getNewNode(int key){
return new Node(key);
}
Node *insert(Node *root, int key){
if(root == nullptr) return getNewNode(key);
if(root->key == key) return root;
if(key < root->key) root->left = insert(root->left, key);
else root->right = insert(root->right, key);
return root;
}
Node *predeccessor(Node *root){
Node *temp = root->left;
while(temp->right) temp = temp->right;
return(temp);
}
Node *erase(Node *root, int key){
if(root == nullptr) return root;
if(key < root->key){
root->left = erase(root->left, key);
}else if(key > root->key){
root->right = erase(root->right, key);
}else{
if(root->left == nullptr && root->right == nullptr){
delete root;
return nullptr;
}else if(root->left == nullptr || root->right == nullptr){
Node *temp = root->left ? root->left : root->right;
delete root;
return temp;
}else {
Node *temp = predeccessor(root);
root->key = temp->key;
root->left = erase(root->left, temp->key);
}
}
return root;
}
void clear(Node *root){
if(root == nullptr) return ;
clear(root->left);
clear(root->right);
delete(root);
return ;
}
void output(Node *root){
if(root == nullptr) return ;
output(root->left);
cout << root->key << " ";
output(root->right);
return ;
}
int main(){
int op, val;
Node *root = nullptr;
while(cin >> op >> val){
switch(op){
case 0: root = insert(root, val); break;
case 1: root = erase(root, val); break;
}
output(root); cout << endl;
}
return 0;
}
AVL树基础知识
名称:AVL树 (平衡二叉排序树)
性质: | H(left) - H(right) | <= 1
优点:由于对每个节点的左右子树的树高做了限制,所以整棵树不会退化成一个链表
左旋 右旋: 仍旧维护了二叉排序树性质的优雅操作
AVL树-失衡类型:LL型 LR型 RL型 RR型
#define NIL (&node::__NIL)
struct node {
node(int key = 0, int h = 0, node *left = NIL, node *right = NIL)
:key(key), left(left), right(right), h(h){}
int key, h;
node *left, *right;
static node __NIL;
};
node node::NIL;
node *getNewNode(int key){
return new node(key, 1);
}
void update_height(node *root){
root->h = max(root->left->h, root->right->h) + 1;
return ;
}
node *left_rotate(node *root){
node *new_root = root->right;
root->right = new_root->left;
new_root->left = root;
update_height(root);
update_height(new_root);
return new_root;
}
node *right_rotate(node *root){
node *new_root = root->left;
root->left = new_root->right;
new_root->right = root;
update_height(root);
update_height(new_root);
return new_root;
}
node *maintain(node *root){
if(abs(root->left->h - root->right->h) < 2) return root;
if(root->left->h > root->right->h) {
if(root->left->right->h > root->left->left->h){
root->left = left_rotate(root->left);
}
root = right_rotate(root);
}else {
if(root->right->left->h > root->right->right->h){
root->right = right_rotate(root->right);
}
root = left_rotate(root);
}
return root;
}
node *insert(node *root, int key){
if(root == NIL) return getNewNode(key);
if(root->key == key) return root;
if(key < root->key){
root->left = insert(root->left, key);
}else{
root->right = insert(root->right, key);
}
update_height(root);
return maintain(root);
}
node *predeccessor(node *root){
node *temp = root->left;
while(temp->right != NIL) temp = temp->right;
return temp;
}
node *erase(node *root, int key){
if(root == NIL) return root;
if(key < root->key){
root->left = erase(root->left, key);
}else if(key > root->key){
root->right = erase(root->right, key);
}else{
if(root->left == NIL || root->right == NIL){
root *temp = (root->left == NIL ? root->right : root->left);
delete root;
return temp;
}else {
node *temp = predeccessor(root);
root->key = temp->key;
root->left = erase(root->left, temp->key);
}
}
update_height(root);
return maintain(root);
}
void clear(node *root){
if(root == NIL) return ;
clear(root->left);
clear(root->right);
cout << "delete" << root->key << endl;
delete root;
return ;
}
void print(node *root){
printf("(%d[%d] | %d, %d )\n", root->key, root->h, root->left->key, root->right->key);
return ;
}
void output(node *root){
if(root == NIL) return ;
print(root);
output(root->left);
output(root->right);
return ;
}
int main(){
int op, val;
node *root = NIL;
while(cin >> op >> val){
switch(op){
case 0: root = insert(root, val); break;
case 1: root = erase(root, val); break;
}
cout << endl << "=====AVL tree point=======" << endl;
output(root);
cout << endl << "=====tree point done=======" << endl;
}
clear(root);
return 0;
}
AVL 刷题
leetcode 面试题 04.06. 后继者
- 运用结构化思维的方式
class Solution {
public:
TreeNode *pre;
TreeNode *inorder(TreeNode *root, TreeNode *p) {
if(root == nullptr) return nullptr;
TreeNode *node;
if(node = inorder(root->left, p)) return node;
if(pre == p) return root;
pre = root;
if(node = inorder(root->right, p)) return node;
return nullptr;
}
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
pre = nullptr;
return inorder(root, p);
}
};
leetcode 450. 删除二叉搜索树中的节点
class Solution {
public:
TreeNode *preccessor(TreeNode *root){
TreeNode *temp = root->left;
while(temp->right) temp = temp->right;
return temp;
}
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 *temp = (root->left ? root->left : root->right);
return temp;
}else{
TreeNode *temp = preccessor(root);
root->val = temp->val;
root->left = deleteNode(root->left, temp->val);
}
}
return root;
}
};
leetcode 1382. 将二叉搜索树变平衡
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 *buildTree(vector<TreeNode *> &nodes, int l, int r){
if(l > r) return nullptr;
int mid = (l + r) >> 1;
TreeNode *root = nodes[mid];
root->left = buildTree(nodes, l, mid - 1);
root->right = buildTree(nodes, mid + 1, r);
return root;
}
TreeNode* balanceBST(TreeNode* root) {
vector<TreeNode *> nodes;
getNodes(root, nodes);
return buildTree(nodes, 0, nodes.size() - 1);
}
};
108. 将有序数组转换为二叉搜索树
class Solution {
public:
TreeNode *buildTree(vector<int> &nums, int l, int r){
if(l > r) return nullptr;
int mid = (l + r) >> 1;
TreeNode *root = new TreeNode(nums[mid]);
root->left = buildTree(nums, l, mid - 1);
root->right = buildTree(nums, mid + 1, r);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return buildTree(nums, 0, nums.size() - 1);
}
};
98. 验证二叉搜索树
class Solution {
public:
int flag;
TreeNode *pre;
bool inorder(TreeNode *root){
if(root == nullptr) return true;
if(!inorder(root->left)) return false;
if(pre != nullptr && root->val <= pre->val){
return false;
}
pre = root;
if(!inorder(root->right)) return false;
return true;
}
bool isValidBST(TreeNode* root) {
pre = nullptr;
return inorder(root);
}
};
501. 二叉搜索树中的众数
class Solution {
public:
int cnt, max_cnt;
TreeNode *now;
void getResult(TreeNode *root, vector<int> &ret){
if(root == nullptr) return ;
getResult(root->left, ret);
if(now->val == root->val){
cnt += 1;
}else{
now = root;
cnt = 1;
}
if(cnt == max_cnt){
ret.push_back(now->val);
}else if(cnt > max_cnt){
max_cnt = cnt;
ret.clear();
ret.push_back(now->val);
}
getResult(root->right, ret);
return ;
}
vector<int> findMode(TreeNode* root) {
cnt = max_cnt = 0;
now = root;
vector<int> ret;
getResult(root, ret);
return ret;
}
};
面试题 17.12. BiNode
class Solution {
public:
TreeNode *head, *pre;
void inorder(TreeNode *root){
if(root == nullptr) return ;
inorder(root->left);
if(pre == nullptr){
head = root;
}else{
pre->right = root;
}
root->left = nullptr;
pre = root;
inorder(root->right);
}
TreeNode* convertBiNode(TreeNode* root) {
head = pre = nullptr;
inorder(root);
return head;
}
};
1008. 前序遍历构造二叉搜索树
class Solution {
public:
TreeNode *buildTree(vector<int> &nums, int l, int r){
if(l > r) return nullptr;
int ind = l + 1;
while(ind <= r && nums[ind] < nums[l]) ++ind;
TreeNode *root = new TreeNode(nums[l]);
root->left = buildTree(nums, l + 1, ind - 1);
root->right = buildTree(nums, ind, r);
return root;
}
TreeNode* bstFromPreorder(vector<int>& preorder) {
return buildTree(preorder, 0, preorder.size() - 1);
}
};
面试题 04.09. 二叉搜索树序列
class Solution {
public:
void mergeSequences(
vector<int> &l, int lind, vector<int> &r, int rind,
vector<int> &buff, vector<vector<int>> &ret
){
if(lind == l.size() && rind == r.size()){
ret.push_back(buff);
return ;
}
if(lind < l.size()){
buff.push_back(l[lind]);
mergeSequences(l, lind + 1, r, rind, buff, ret);
buff.pop_back();
}
if(rind < r.size()){
buff.push_back(r[rind]);
mergeSequences(l, lind, r, rind + 1, buff, ret);
buff.pop_back();
}
return;
};
vector<vector<int>> BSTSequences(TreeNode* root) {
vector<vector<int>> ret;
if(root == nullptr){
ret.push_back(vector<int>());
return ret;
}
vector<vector<int>> l_arr = BSTSequences(root->left);
vector<vector<int>> r_arr = BSTSequences(root->right);
for(auto l : l_arr){
for(auto r : r_arr){
vector<int> buff;
buff.push_back(root->val);
mergeSequences(l, 0, r, 0, buff, ret);
}
}
return ret;
}
};