手撕AVL树

二叉排序树基础知识

名称:二叉排序树、二叉搜索树
性质:
1 左子树 < 根节点
2 右子树 > 根节点
用途:解决与排名相关的检索需求

二叉查找树的删除

  1. 删除叶子节点(出度为0的节点) 直接删除
  2. 删除出度为1的节点 提升该节点的唯一子树
  3. 删除出度为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;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值