二叉树各种遍历方式(递归与非递归)

  • 二叉树简述

1、第i层至多有2的 i -1次方个结点;

2、深度为k的二叉树至多有2^(k) -1个结点;

3、叶子结点个数为n,双结点个数为m,则  n = m + 1

4、递归遍历方式代码简单,效率低;非递归遍历方式代码较复杂,效率高

5、层序遍历需要借助(queue)实现,前、中、后序遍历需借助栈(stack)实现。

  • 节点定义

typedef struct Node_t{
    
    struct Node_t * left;
    struct Node_t * right;
    int                value;
    Node_t(int a):value(a),left(NULL),right(NULL)
    {
    }
}Node_t;
  • 先(前)序遍历。

访问顺序:value——>左子树——>右子树

1、递归算法

void preOrderRecursion(Node_t *root){
  if(root){
    visit(root);
    preOrderRecursion(root->left);
    preOrderRecursion(root->right);
  }
}

2、非递归算法

思路:root节点先进栈,访问栈顶元素,访问后出栈同时,右节点先入栈,左节点再入栈。

void preOrder(Node_t *root){
  if(!root){
    return;
  }
  stack<Node_t *> S;
  Node_t *p = root;
  S.push(root);
  while(!S.empty()){
    p = S.top();
    visit(p);
    S.pop();
    if(p->right){
      S.push(p->right);
    }
    if(p->left){
      S.push(p->left);
    }
  }
}
  • 中序遍历

访问顺序:左子树——>value——>右子树

1、递归算法

void midOrderRecursion(Node_t *root){
  if(root){
    midOrderRecursion(root->left);
    visit(root);
    midOrderRecursion(root->right);
  }
}

2、非递归算法

思路:root节点先进栈,循环将左子树入栈,开始访问栈顶元素,访问后出栈同时将栈顶元素的右子树入栈。

void midOrder(Node_t *root){
  stack<Node_t *> S;
  S.push(root);
  Node_t *p = root;
  while(!S.empty()){
    p = S.top();
    while(p){
      S.push(p->left);
      p = p->left;
    }
    S.pop();   //pop out the nullptr
    if(!S.empty()){
      p = S.top();
      visit(p);
      S.pop();
      S.push(p->right);//push its right child into the stack
    }
  }
}
  • 后序遍历

访问顺序:左子树——>右子树——>value

1、递归算法

void postOrderRecursion(Node_t *root){
  if(root){
    postOrderRecursion(root->left);
    postOrderRecursion(root->right);
    visit(root);
  }
}

2、非递归算法

思路:循环将左子树入栈,开始检查栈顶元素的右子树,如果右子树为空或者右子树已被访问,即可访问当前栈顶元素。

如果之前访问过的节点last恰为该节点的右节点,说明其右子树已经访问完,应该访问该栈顶元素。

void postOrder(Node_t *root){
  Node_t *last = nullptr;
  Node_t *p = root;
  stack<Node_t *> S;
  while( p || !S.empty()){
    while(p){
      S.push(p);
      p = p->left;
    }
    p = S.top();
    if(p->right && p->right != last){
      p = p->right;
    }else{
      visit(p);
      S.pop();
      last = p;
      p = nullptr; //p needs to be updated to null for next loop
    }
  }
}
  • 层序遍历

思想:需要借助queue来对节点进行缓存,先进队列的节点需要先离开

void levelOrder(Node_t *root){
  if(!root){
    return;
  }
  queue<Node_t *> Q;
  Node_t *p = nullptr;
  Q.push(root);
  while(!Q.empty()){
    p = Q.front();
    Q.pop();
    visit(p);
    if(p->left){
      Q.push(p->left);
    }
    if(p->right){
      Q.push(p->right);
    }
  }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值