目录
后序:(对前序进行了一点改变,变成先压左再右,并弹出到备用栈里面,打印备用栈)
二叉树的深度遍历
深入学习二叉树(一) 二叉树基础 - 简书 (jianshu.com)https://www.jianshu.com/p/bf73c8d50dc2
三种遍历方法(采用递归实现)
先序:头左右
/**
* 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 front(TreeNode* root,vector<int >&result){
if(root==nullptr){return ;}
result.push_back(root->val);
front(root->left,result);
front(root->right,result);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
front(root,result);
return result; }
};
中序:左头右
/**
* 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 InOrderTraverse(TreeNode* T,vector<int>&a){
if(T==nullptr){return;}
InOrderTraverse(T->left,a);
a.push_back(T->val);
InOrderTraverse(T->right,a);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
InOrderTraverse(root,result);
return result;
}
};
后序:左右头
/**
* 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 back(TreeNode* root,vector<int>&result){
if(root==nullptr){return;}
back(root->left,result);
back(root->right,result);
result.push_back(root->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int >result;
back(root,result);
return result;
}
};
非递归实现:(栈)
先序:
先把根节点压进去( s.push() )
1:从栈中弹出一个节点( s.pop() )
2:打印(处理)该节点
3:先右后左压入栈(如果有)
4:循环往复。
/**
* 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:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>p;
p.push(root);
if(root==nullptr){return result;}
while(!p.empty()){
result.push_back(p.top()->val);
root=p.top();p.pop();
if(root->right!=nullptr)p.push(root->right);
if(root->left!=nullptr)p.push(root->left);
}
return result;
}
};
中序:(虽然也是用栈,但是要写一个“全压左”的子函数)
树的左边界都压进去,然后弹出并打印(处理),弹出的过程中判断是否存在右节点,如果有将该右节点下属的的子树的左边界都压进去,循环往复。
/**
* 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:
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
if(root==nullptr){return result;}
stack<TreeNode*>p;
TreeNode *head=root;
while(head!=nullptr){
p.push(head);
head=head->left;
}//将左边界都压入栈内
while(!p.empty()){
result.push_back(p.top()->val);
TreeNode *head2=p.top();
//写入栈顶并且用head2表示栈顶,防止弹出后找不到
p.pop();
if(head2->right!=nullptr){//如果有右子节点的情况下,将右子树的左边界全部压入栈
TreeNode *youhead=head2->right;
while(youhead!=nullptr){
p.push(youhead);
youhead=youhead->left;
}
}
}
return result;
}
};
后序:(对前序进行了一点改变,变成先压左再右,并弹出到备用栈里面,打印备用栈)
准备两个栈,先把头节点压到栈1中。
1:弹出该节点并压到栈2里面。
2:往栈1里面先压左再压右(如果有)
3:循环往复
依次打印(处理)弹出栈2里面的节点。
/**
* 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:
vector<int> postorderTraversal(TreeNode* root) {
vector<int >result;
if(root==nullptr){return result;}
stack<TreeNode*>p;
stack<TreeNode*>q;
p.push(root);
while(!p.empty()){
q.push(p.top());
TreeNode *head;
head=p.top();
p.pop();
if(head->left!=nullptr){p.push(head->left);}
if(head->right!=nullptr){p.push(head->right);}
}
while(!q.empty()){
result.push_back(q.top()->val);
q.pop();
}
return result;
}
};
二叉树的宽度(按层)遍历
宽度遍历用队列(先进先出)
1)先把头节点放入队列中
2)每次弹出一个,打印
3)对于弹出的节点,先把弹出节点的左节点放入队列、再把其右节点放入队列(没有左右节点就不放)
重复以上三个步骤:
/**
* 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:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
if(root==nullptr){return result;}
queue<TreeNode*>p;//宽度遍历用队列
p.push(root);
while(!p.empty()){
result.push_back(p.front()->val);
TreeNode *head=p.front();
p.pop();
if(head->left!=nullptr){p.push(head->left);}
if(head->right!=nullptr){p.push(head->right);}
}
return result;
}
};
求一个二叉树的最大宽度
思路,在宽度遍历的基础上进行改进:
curLevel:记录当前Node所在层数 curWidth:记录当前层的宽度 maxWidth:记录全局最大层的宽度
1、新增一个HashMap,用于记录当前Node属于哪一层
2、每次添加Node进队列时,记录当前Node所在层次
3、每次poll出一个Node时,在HashMap中获取它属于哪一层,如果属于当前层,curWidth++。反之 maxWidth = Math.max(maxWidth, curWidth) , curLevel++
以下列题目为例:
/**
* 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:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
if(root==nullptr){return result;}
queue<TreeNode*>p;
p.push(root);
unordered_map<TreeNode*,int>hashable;
int x=0;
hashable[root]=0;//根位于第0层;
result.push_back({});
while(!p.empty()){
if( hashable[p.front()] !=x ){result.push_back({});}
//判断当前待处理的头元素的层数是否和上一个被处理后踢出队列的头元素的层数相等。
//如果不相等,则意味着来到了新的一层,需要将结果向量增加一个维,以准备写入新的一层的元素。
x=hashable[p.front()];//表示当前头元素的层数
result[x].push_back(p.front()->val);
TreeNode *head;
head=p.front();;
p.pop();
if(head->left!=nullptr){p.push(head->left);hashable[head->left]=x+1;}
if(head->right!=nullptr){p.push(head->right);hashable[head->right]=x+1;}
}
return result;
}
};
判断当前待处理的头元素的层数是否和上一个被处理后踢出队列的头元素的层数相等。如果不相等,则意味着来到了新的一层,需要将结果向量增加一个维,以准备写入新的一层的元素。
关于栈和队列的知识:
定义栈:stack<数据类型:可以是int、TreeNode*等>名称;
压:p.push(被压元素);
弹:p.pop(); 弹出栈顶的元素
p.empty() 如果栈中元素个数为0返回true,栈不为空返回false
p.top() 返回栈顶部的元素
p.size() 返回栈中元素的个数
定义队列:queue<数据类型:可以是int、TreeNode*等>名称;
压:q.push(被压元素);
弹:q.pop(); 弹出队列头部的元素
q.empty() 如果栈中元素个数为0返回true,栈不为空返回false
q.front() 返回队列头部的元素
q.size() 返回队列元素的个数
C++数据结构——栈_GeekZW的博客-CSDN博客_c++栈https://blog.csdn.net/zichen_ziqi/article/details/80807989C++数据结构——队列_GeekZW的博客-CSDN博客_c++队列https://blog.csdn.net/zichen_ziqi/article/details/80819939