目录
1.前序遍历
前序遍历即DLR,先访问根节点再访问左子树,再访问右子树,因此需要遍历和回溯
递归:递归遍历左子树,遍历的同时,用list保存节点的值用s保存遍历过的节点,走到底之后就回溯,访问上一个节点的有节点,重复以上过程,直到访问到最后一个节点(左右都为空)
java:
class Solution {
List<Integer> list=new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root==null) return list;
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
}
c++:
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
if(root==NULL) return res;
res.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
return res;
}
};
非递归:其实在递归的过程中隐含着一个栈,用非递归的方法来实现的时候,我们就要把栈显示的表示出来,先访问根节点,因此在遍历的时候,用list来保存根节点的值,用一个栈来保存根节点,一直到访问到最左下的一个节点(即此时node=null),再从栈中取出节点,对每一个节点继续遍历重复这个过程,一直到栈和节点的左右孩子都空
java:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<Integer>();
if(root==null) return list;
Deque<TreeNode> s=new LinkedList<TreeNode>();
TreeNode node=root;
while(!s.isEmpty()||node!=null){
while(node!=null){
list.add(node.val);
s.push(node);
node=node.left;
}
node=s.pop();
node=node.right;
}
return list;
}
}
c++:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if(root==NULL) return res;
stack<TreeNode *> s;
TreeNode* node=root;
while(node!=NULL||!s.empty()){
while(node!=NULL){
res.push_back(node->val);
s.push(node);
node=node->left;
}
node=s.top();
s.pop();
node=node->right;
}
return res;
}
};
2.中序遍历
中序遍历就是LDR,先访问左子树,再访问根节点最后访问右子树,也需要遍历和回溯
递归:从根节点开始,遍历左子树到最左侧的节点并保存节点的值,与前序遍历不同的是,中序遍历一直到最左下的节点再开始保存节点的值,然后回溯
java:
class Solution {
List<Integer> list=new ArrayList();
public List<Integer> inorderTraversal(TreeNode root) {
if(root==null) return list;
inorderTraversal(root.left);
list.add(root.val);
inorderTraversal(root.right);
return list;
}
}
c++:
class Solution {
public:
vector<int> res;
vector<int> inorderTraversal(TreeNode* root) {
if(root==NULL) return res;
inorderTraversal(root->left);
res.push_back(root->val);
inorderTraversal(root->right);
return res;
}
};
非递归:同前序遍历,中序遍历递归的过程也是隐含了一个栈的调用,我们在迭代的时候,将栈显示的表示出来,从根节点开始遍历,一直到最左下的节点,遍历的过程用s保存该节点的值,每次遍历结束就用list保存该节点的值,并访问该节点的右节点重复上述过程,直到栈和节点的左右孩子都空
java:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
if(root==null) return list;
Deque<TreeNode> s=new LinkedList();
TreeNode node=root;
while(node!=null||!s.isEmpty()){
while(node!=null){
s.push(node);
node=node.left;
}
node=s.pop();
list.add(node.val);
node=node.right;
}
return list;
}
}
c++:
class Solution {
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> res;
while(!s.empty()||root!=NULL){
while(root!=NULL){
s.push(root);
root=root->left;
}
TreeNode *pr=s.top();
s.pop();
res.push_back(pr->val);
root=pr->right;
}
return res;
}
};
3.后序遍历
后序遍历即LRD,先访问左子树,再访问右子树,最后访问根节点,因此也需要遍历和回溯
递归:从根节点开始,递归访问左子树,再递归访问右子树,最后访问根节点,因此,每一轮的递归结束后再保存节点的值
java:
class Solution {
List<Integer> list=new ArrayList();
public List<Integer> postorderTraversal(TreeNode root) {
if(root==null) return list;
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}
c++:
class Solution {
public:
vector<int> res;
vector<int> postorderTraversal(TreeNode* root) {
if(root==NULL) return res;
postorderTraversal(root->left);
postorderTraversal(root->right);
res.push_back(root->val);
return res;
}
};
非递归:后序遍历不能像前序和中序遍历一样来只用栈回溯了,因为我们在回溯的过程,并不知道上一个节点是左节点还是右节点,只有访问过右节点我们才能访问根节点,如果是左节点,我们就要先访问右节点再访问根节点,因此,我们需要额外添加一个变量来保存上一个访问的节点(prenode),如果正在访问的节点(curnode)的右节点是prenode或者为null,说明右节点已被访问或者没有右节点,那就可以直接保存curnode,但如果不是,那就需要先访问右节点,每次访问结束都应该修改prenode为curnode
java:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
if(root==null) return list;
Deque<TreeNode> s=new LinkedList();
TreeNode preNode=null;
TreeNode curNode=root;
while(curNode!=null){
s.push(curNode);
curNode=curNode.left;
}
while(!s.isEmpty()){
curNode=s.pop();
if(curNode.right==null||curNode.right==preNode){
list.add(curNode.val);
preNode=curNode;
}
else{
s.push(curNode);
curNode=curNode.right;
while(curNode!=null){
s.push(curNode);
curNode=curNode.left;
}
}
}
return list;
}
}
c++:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
TreeNode *preNode=NULL;
TreeNode *curNode=root;
vector<int> res;
if(root==NULL) return res;
stack<TreeNode*> s;
while(curNode!=NULL){
s.push(curNode);
curNode=curNode->left;
}
while(!s.empty()){
curNode=s.top();
s.pop();
if(curNode->right==NULL||curNode->right==preNode){
res.push_back(curNode->val);
preNode=curNode;
}
else{
s.push(curNode);
curNode=curNode->right;
while(curNode){
s.push(curNode);
curNode=curNode->left;
}
}
}
return res;
}
};
4.层序遍历
层序遍历即一层层的访问,那就不需要回溯,但需要有一个队列来保存当前节点值,这样就可以通过该节点去访问它的孩子节点,直到访问到叶子节点结束
java:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
Queue<TreeNode> q=new LinkedList();
if(root==null) return list;
q.add(root);
while(!q.isEmpty()){
TreeNode p=q.poll();
list.add(p.val);
if(p.left!=null){
q.add(p.left);
}
if(p.right!=null){
q.add(p.right);
}
}
return list;
}
}
c++:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
queue<TreeNode*> q;
vector<int> res;
if(root==NULL) return res;
q.push(root);
while(!q.empty()){
TreeNode *p=q.front();
q.pop();
res.push_back(p->val);
if(p->left!=NULL) q.push(p->left);
if(p->right!=NULL) q.push(p->right);
}
return res;
}
};
其实非递归可以背一个模板来用 我真聪明
while(!s.empty()||root!=NULL){
while(root!=NULL){
s.push(root);
root=root->left;
//前序在这里加上res.push_back(pr->val);
}
TreeNode *pr=s.top();
s.pop();
//中序在这里加上res.push_back(pr->val);
root=pr->right;
//后序要在这里判断右节点再做相应操作
}
return res;
终于写完啦耶,希望能够帮到大家,欢迎留言和提问,如有错误,欢迎指正,创作不易,谢谢支持