二叉树的种类、遍历方式 及力扣常见题型
作者:互联网
一、二叉树的种类
1、满二叉树
除最后一层无任何子节点外,每一层上的所有结点都有两个子结点二叉树(若深度为k,有2^k-1个节点)。
2、完全二叉树
设一棵二叉树深度为h。除了第h层外,其它各层的结点数都达到最大个数,且第h层(最下面一层)的所有结点都连续集中在最左边,该层包含 1~ 2^h -1 个节点。。
3、二叉搜索树(二叉查找树,二叉排序树)
二叉搜索树是有数值的,且是一个有序树, 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树 。
二叉搜索树会出现平衡问题:
二叉搜索树在经过多次插入与删除后,有可能导致上面右图的结构: 搜索性能已经是线性的了,所以,使用二叉搜索树还要考虑尽可能保持上面左图的结构,和避免上面右图的结构,也就是所谓的“平衡”问题 。
为了解决这种情况,所以出现了下面我即将谈到的平衡二叉搜索树。
4、平衡二叉搜索树 (AVL树)
AVL树也规定了左结点小于根节点,右结点大于根节点。并且还规定了左子树和右子树的高度差不得超过1,这样保证了它不会成为线性的链表。AVL树主要就是通过左旋和右旋来解决平衡问题。
二、二叉树的创建
//初始化列表形式,初始化节点
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){}
};
//根据数组构造完全二叉树
TreeNode *creatMytree(vector<int>& Mytree,int index,int len){
if(index>=len) return nullptr;
TreeNode *t=new TreeNode(Mytree[index]);
t->left=creatMytree(Mytree,index*2+1,len);
t->right=creatMytree(Mytree,index*2+2,len);
return t;
}
//根据前序遍历创建任意二叉树
TreeNode* deserialize_dfs(list<string>& dataArray){
if(!dataArray.size() ) return nullptr;
if(dataArray.front()=="None"){
dataArray.erase(dataArray.begin());
return nullptr;
}
TreeNode* node=new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin());
node->left=deserialize_dfs(dataArray);
node->right=deserialize_dfs(dataArray);
return node;
}
int main()
{
//根据数组创建完全二叉树
vector<int> Mytree={5,4,6,1,2,7,8};
int len=Mytree.size();
TreeNode *root=creatMytree(Mytree,0,len);
//根据前序遍历创建任意二叉树
list<string> dataArray={"1","2","4","None","None","None","3","None","None"};
TreeNode *root1=deserialize_dfs(dataArray);
getchar();
return 0;
}
三、二叉树的遍历
二叉树的遍历有以下几种方式:
1、深度优先遍历
前序遍历(递归法,迭代法):中左右 5 4 1 2 6 7 8
中序遍历(递归法,迭代法):左中右 1 4 2 5 7 6 8
后序遍历(递归法,迭代法):左右中 1 2 4 7 8 6 5
2、广度优先遍历
层次遍历(迭代法):5 4 6 1 2 7 8
代码如下:
//前序遍历:中左右
//1、递归法
void preorderTraversal(TreeNode *cur,vector<int>& res){
if(!cur) return;
res.push_back(cur->val);
preorderTraversal(cur->left,res);
preorderTraversal(cur->right,res);
}
//2、迭代法
void preorderStk(TreeNode *cur,vector<int>& res){
stack<TreeNode*> stk;
while(cur || !stk.empty()){
while(cur){
res.push_back(cur->val); //中
stk.push(cur);
cur=cur->left; //左
}
cur=stk.top();
stk.pop();
cur=cur->right; //右
}
}
//中序遍历:左中右
//1、递归法
void inorderTraversal(TreeNode *cur,vector<int>& res){
if(!cur) return;
inorderTraversal(cur->left,res);
res.push_back(cur->val);
inorderTraversal(cur->right,res);
}
//2、迭代法
void inorderStk(TreeNode *cur,vector<int>& res){
stack<TreeNode*> stk;
while(cur || !stk.empty()){
while(cur){
stk.push(cur);
cur=cur->left; //左
}
cur=stk.top();
stk.pop();
res.push_back(cur->val); //中
cur=cur->right; //右
}
}
//后序遍历:左右中
//1、递归法
void postorderTraversal(TreeNode *cur,vector<int>& res){
if(!cur) return;
postorderTraversal(cur->left,res);
postorderTraversal(cur->right,res);
res.push_back(cur->val);
}
//2、迭代法
void postorderStk(TreeNode *cur,vector<int>& res){
stack<TreeNode*> stk;
TreeNode* pre;
while(cur || !stk.empty()){
while(cur){
stk.push(cur);
cur=cur->left; //左
}
cur=stk.top();
stk.pop();
if(cur->right==nullptr || cur->right==pre){//只有在右节点为空,或者右节点之前已经放进res了,才能把cur放进res
res.push_back(cur->val); //中
pre=cur;
cur=nullptr; //避免cur重复放入
}
else{
stk.push(cur);//右子树还有节点没有遍历到,cur重新入栈
cur=cur->right; //右
}
}
}
//层序遍历
vector<vector<int>> levelOrder(TreeNode *root){
vector<vector<int>> res;
vector<int> temp;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size=q.size();
for(int i=0;i<size;i++){
TreeNode *node=q.front();
q.pop();
if(node->left){
q.push(node->left);
}
if(node->right){
q.push(node->right);
}
temp.push_back(node->val);
}
res.push_back(temp);
temp.clear();
}
return res;
}
四、力扣常见二叉树有关题型
//判断是否是对称二叉树
class Solution {
public:
bool compare(TreeNode* l,TreeNode* r){
if(!l&&!r) return true;
else if(!l||!r) return false;
return (l->val==r->val) && compare(l->left,r->right) && compare(l->right,r->left);
}
bool isSymmetric(TreeNode* root) {
return compare(root,root);
}
};
class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
return max(maxDepth(root->left),maxDepth(root->right))+1;
}
};
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(!root) return nullptr;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
//判断是否是平衡二叉树
class Solution {
public:
int depth(TreeNode* root){
if(!root) return 0;
return max(depth(root->left),depth(root->right))+1;
}
bool isBalanced(TreeNode* root) {
if(!root) return true;
return (abs(depth(root->left)-depth(root->right))<=1) && isBalanced(root->left) && isBalanced(root->right);
}
};
class Solution {
public:
bool search(TreeNode* root,long long low,long long high){
if(!root)
return true;
if(root->val>=high||root->val<=low)
return false;
return search(root->left,low,root->val)&&search(root->right,root->val,high);
}
bool isValidBST(TreeNode* root) {
return search(root,LONG_MIN,LONG_MAX);
}
};
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
TreeNode* merged=new TreeNode(root1->val+root2->val);
merged->left=mergeTrees(root1->left,root2->left);
merged->right=mergeTrees(root1->right,root2->right);
return merged;
}
};
class Solution {
public:
void flatten(TreeNode* root) {
vector<TreeNode*>l;
preorderTraversal(root,l);
int size=l.size();
for(int i=1;i<size;i++)
{
TreeNode *pre=l[i-1],*cur=l[i];
pre->left=nullptr;
pre->right=cur;
}
}
void preorderTraversal(TreeNode* root,vector<TreeNode*> &l) {
if(!root)
return;
l.push_back(root);
preorderTraversal(root->left,l);
preorderTraversal(root->right,l);
}
};
class Solution {
public:
TreeNode* myTree(const unordered_map<int,int>& hashmap,vector<int>& preorder, vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
if(preorder_left>preorder_right) return nullptr;
int preorder_root=preorder[preorder_left];
int pIndex=hashmap.at(preorder_root);
TreeNode* root=new TreeNode(preorder_root);
int left_size=pIndex-inorder_left;
root->left=myTree(hashmap,preorder,inorder,preorder_left+1,preorder_left+left_size,inorder_left,pIndex-1);
root->right=myTree(hashmap,preorder,inorder,preorder_left+left_size+1,preorder_right,pIndex+1,inorder_right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
unordered_map<int,int> hashmap;
for(int i=0;i<inorder.size();i++){
hashmap[inorder[i]]=i;
}
return myTree(hashmap,preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
};
标签:题型,right,TreeNode,cur,及力,二叉树,return,root,left 来源: https://blog.csdn.net/qq_41251638/article/details/122665126