(二十五)二叉树的递归与非递归遍历

概述

1. 二叉树的递归序

在这里插入图片描述
而所谓的前中后序则为递归序中数字出现的次序

  • 前序(第一次出现):1,2,4,5,3,6,7
  • 中序(第二次出现):4,2,5,1,6,3,7
  • 后序(第三次出现):4,5,2,6,7,3,1

2. 二叉树的遍历方式

  • 深度优先遍历
    • 前序遍历(递归法,非递归法)
    • 中序遍历(递归法,非递归法)
    • 后序遍历(递归法,非递归法)
  • 广度优先遍历
    • 层次遍历(非递归法)

1.递归遍历

前中后序指的就是中间节点的位置,即

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

树的节点

struct TreeNode{
    int value;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val): value(val),left(NULL),right(NULL){}
};

1.1 先序遍历

void preOrderRecur(TreeNode* head){
    if(head ==  NULL){/*递归停止条件*/
        return ;
    }
    cout << head->value << " ";
    preOrderRecur(head->left);
    preOrderRecur(head->right);
}

1.2 中序遍历

void inOrderRecur(TreeNode* head){
    if(head == NULL){
        return ;
    }
    inOrderRecur(head->left);
    cout << head->value << " ";
    inOrderRecur(head->right);
}

1.3 后序遍历

void posOrderRecur(TreeNode* head){
    if(head == NULL){
        return ;
    }
    posOrderRecur(head->left);
    posOrderRecur(head->right);
    cout << head->value << " ";
}

2. 非递归遍历

2.1 先序遍历

实现步骤:

  • 步骤1:申请一个栈sta,把头节点压入栈中
  • 步骤2:从sta中弹出栈顶节点,记为cur,打印节点cur的值;再将节点cur的右孩子(若不为空)压入栈中,最后将节点cur的左孩子(若不为空)压入栈中。
  • 步骤3:不断重复步骤2,直到栈为空,则结束。

在这里插入图片描述

在这里插入图片描述

void preOrderUnRecur(TreeNode* head){
    cout << "pre-order-UnRecur: " << endl;
    if(head == NULL){
        return ;
    }
    stack<TreeNode*> sta;
    sta.push(head);
    while(!sta.empty()){
        TreeNode* cur = sta.top();/*每次弹出都会更新*/
        cout << cur->value << " ";
        sta.pop();
        
        if(cur->right != NULL) sta.push(cur->right);
        if(cur->left != NULL) sta.push(cur->left);
    }
    cout << endl;
}

2.2 中序遍历

实现步骤:

  • 步骤1:申请一个栈sta,初始时,令cur = head;
  • 步骤2:先把cur节点压入栈中,对cur节点为头节点的整颗子树来说,依次把左边界压入栈中,即不停的令cur = cur->left;然后重复步骤2;
  • 步骤3:不断重复步骤2,直到cur为空,此时从栈中弹出一个节点,记为node,打印node的值,并让cur = cur->right;然后继续重复步骤2.
  • 步骤4:栈为空且cur为空时,则停止
void inOrderUnRecur(TreeNode* head){
    cout << "In-order-UnRecur:" << endl;
    if(head != NULL){
        stack<TreeNode*> sta;
        TreeNode* cur = head;
        while(!sta.empty() || cur != NULL){
            if(cur != NULL){
                sta.push(cur);
                cur = cur->left;
            }else{
                cur = sta.top();
                cout << cur->value << " ";
                sta.pop();
                cur = cur->right;
            }
        }
    }
    cout << endl;
}

2.3 后序遍历

实现步骤:

  • 步骤1:申请一个栈s1,然后把头节点压入s1;
  • 步骤2:从sta中弹出栈顶节点,记为cur,打印节点cur的值;再将节点cur的左孩子(若不为空)压入栈中,最后将节点cur的右孩子(若不为空)压入栈中【此过程与前序相反】。在整个过程中,把s1弹出的的节点放入另一个栈s2中;
  • 不断重复步骤2,直到s1为空,过程停止
  • 从s2中依次弹出节点并打印。【s2就相当于一个反转的过程,s1弹出节点的顺序为中右左,经s2打印出来为左右中,即为后序】
void posOrderUnRecur(TreeNode* head){
    cout << "pos-order-UnRecur:" << endl;
    if(head != NULL){
        stack<TreeNode*> s1;
        stack<TreeNode*> s2;
        s1.push(head);
        TreeNode* cur = NULL;
        while(!s1.empty()){
            cur = s1.top();
            s2.push(cur);
            s1.pop();

            if(cur->left != NULL) s1.push(cur->left);
            if(cur->right != NULL) s1.push(cur->right);
        }

        while(!s2.empty()){
            cout << s2.top()->value << " ";
            s2.pop();
        }
    }
    cout << endl;
}

3. 测试

#include <iostream>
#include <stack>
using namespace std;
/*树的节点*/
struct TreeNode{
    int value;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val): value(val),left(NULL),right(NULL){}
};
/*创建一棵树*/
TreeNode* createTree(){
    TreeNode* head = new TreeNode(1);
    head->left = new TreeNode(2);
    head->right = new TreeNode(3);
    head->left->left = new TreeNode(4);
    head->left->right = new TreeNode(5);
    head->right->left = new TreeNode(6);
    head->right->right = new TreeNode(7);

    return head;
}

int main(){
    
    TreeNode* head = createTree();
    cout << "pre-order-recur" << endl;
    preOrderRecur(head);
    cout << endl;
    preOrderUnRecur(head);

    cout << "in-order-recur:" << endl;
    inOrderRecur(head);
    cout << endl;
    inOrderUnRecur(head);

    cout << "pos-order-recur:" << endl;
    posOrderRecur(head);
    cout << endl;
    posOrderUnRecur(head);
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值