满二叉树、完全二叉树、二叉搜索树
满二叉树:只有度为0或2的结点,并且度为0的结点在同一层上
完全二叉树:除了最底层结点可能没填满,其他各层都填满了,并且最底层的结点都集中在最左边。
以上是没数值的树
二叉搜索树:是有数值的树,而且保持有序
二叉树的存储方式
链式存储、顺序存储(数组)
顺序存储:对于下标为i的节点,左孩子是i2+1,右孩子是i2+2
链式存储:
struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};
二叉树的遍历、插入、反转
class Solution {public:void dfs(TreeNode *p) {if(p->left) dfs(p->left);cout<<p->val<<' ';if(p->right) dfs(p->right);}TreeNode* add(TreeNode *p, int value) {if(p == nullptr) {return new TreeNode(value);}else if(p->val > value) {p->left = add(p->left, value);return p;}else if(p->val < value) {p->right = add(p->right, value);return p;}}TreeNode* invertTree(TreeNode* root) {if(root == nullptr) return root;swap(root->left, root->right);root->left = invertTree(root->left);root->right = invertTree(root->right);return root;}};
二叉树的顺序存储
// 二叉树的数组初始化TreeNode* init(vector<int> v) {if(v.size()==0) return nullptr;TreeNode* root = new TreeNode(v[0]);queue<TreeNode*> q;q.push(root);for(int i=1;i<v.size();i++) {TreeNode* tmp = q.front();q.pop();if(v[i]!=-1) {tmp->left = new TreeNode(v[i]);q.push(tmp->left);}if(v[++i]!=-1) {tmp->right = new TreeNode(v[i]);q.push(tmp->right);}}return root;}
完全二叉树深度的利用
https://leetcode-cn.com/problems/count-complete-tree-nodes/
log*log时间复杂度计算完全二叉树节点个数
pair<int,int> countDepth(TreeNode* p) {int l=0, r=0;while(p) {l++;p=p->left;}while(p) {r++;p=p->right;}return make_pair(l,r);}int countNodes(TreeNode* root) {if(root==nullptr) return 0;int res = 1;auto left = countDepth(root->left);if(left.first == left.second) {res+=(1<<left.first)-1;}else {res+=countNodes(root->left);}auto right = countDepth(root->right);if(right.first == right.second) {res+=(1<<right.first)-1;}else {res+=countNodes(root->right);}return res;}
平衡二叉树
最近公共祖先
方法一:求LCA(x,y)只需要从x向上遍历到根节点并且把每个节点标记,然后从y向上遍历知道需要标记过的节点
方法二:fx代表x节点的后代中是否有x或y,那么lca就是满足左右子树都包含x或y,或者本身是x或y且左子树或右子树包含x或y
方法三:如果是有序二叉树,还可以利用节点在区间内来判断节点是否在子树内
