二叉树的四种遍历方式(递归or非递归/C++)

0.简介

1.先序遍历

2.中序遍历

3.后序遍历

4.按层遍历

0.简介

        二叉树的遍历可以分为先序、中序、后序和按层遍历。前三者可以用递归的方式实现,也可以借助栈非递归地遍历。按曾遍历则是借助队列来实现。递归版非常简单,这里只介绍非递归版,该方式均在循环中完成。

        先序遍历:(+-8/625)如果当前节点不为空,输出当前节点的值。如果其左节点不为空,则将当前节点入栈,再移动到其左节点;如果左节点为空,从栈中取出一个节点作为当前节点(栈空则结束循环),再移动到其右节点。

        中序遍历:(8-6/2+5)当前节点的左节点非空,则当前节点入栈,否则输出当前节点的值(左节点为空,当前节点就是中间节点)。然后判断栈是否为空,是则退出循环,否则取出一个节点作为当前节点,输出其值(栈中的节点的左节点已经被访问,因此都是中间节点),再移动到其右节点。

        后续遍历:(862/-5+)该方式需要借助标记左、右节点是否存在或被访问,因此需要借助额外变量辅助。当前节点的左节点存在且未被访问,则将当前节点的左节点标记为被访问将当前节点和其状态入栈,并移动到左节点;如果左节点为空,但右节点存在且未被访问,则将当前节点的右节点标记为被访问将当前节点和其状态入栈,并移动到右节点;如果左右节点为空或是被访问,则输出当前节点的值,此时栈为空则结束循环,否则取出一个节点未当前节点。

        按层遍历:(+-58/62)

二叉树的结构

//结构
struct Node {
    char val;
    struct Node* rnext;
    struct Node* lnext;
    Node() {
        val = NULL;
        rnext = NULL;
        lnext = NULL;
    }
};

//状态
struct NodeState {
    Node* p;
    int state; //0 未访问 1 访问左节点 2 访问右节点
};

1.先序遍历

void preorderTraversal(Node* head) {
    if (head != NULL) {
        cout << head->val;
        preorderTraversal(head->lnext);
        preorderTraversal(head->rnext);
    }
}
//先序遍历
void preorderTraversal(Node* head) {
    stack<Node*> stk;
    Node* p = head;
    while (p != NULL) {
        //先输出节点的值,如果左节点不为空,移动到左节点;
        //如果左节点为空且栈不为空,从栈中取出一个节点,移动到该节点的右节点;
        //如果栈为空结束循环。
        cout << p->val;
        if (p->lnext != NULL) {
            stk.push(p);
            p = p->lnext;
        }
        else if (!stk.empty()) {
            p = stk.top();
            stk.pop();
            p=p->rnext;
        }
        else break;
    }
}

2.中序遍历

void inorderTraversal(Node* head) {
    if (head != NULL) {
        inorderTraversal(head->lnext);
        cout << head->val;
        inorderTraversal(head->rnext);
    }
}
//中序遍历
void inorderTraversal(Node* head) {
    stack<Node*> stk;
    Node* p = head;
    while (p != NULL) {
        if (p->lnext != NULL) {
            stk.push(p);
            p=p->lnext;
        }
        else {
            //遍历左节点,左节点为空,输出当前节点的值;
            //从栈中取出一个节点,先输出该节点的值,如果该节点的右节点不为空,移动到右节点;
            //如果栈为空,结束循环。
            cout << p->val;
            if (!stk.empty()) {
                p = stk.top();
                stk.pop();
                cout << p->val;
                p = p->rnext;
            }
            else break;
        }
    }
}

3.后序遍历

void postorderTraversal(Node* head) {
    if (head != NULL) {
        postorderTraversal(head->lnext);
        postorderTraversal(head->rnext);
        cout << head->val;
    }
}
//后序遍历
void postorderTraversal(Node* head) {
    stack<NodeState> stk;
    NodeState ns = { head,0 };
    while (ns.p != NULL) {
        if (ns.p->lnext != NULL && ns.state <1) {//节点未访问
            stk.push({ns.p,1});
            ns = { ns.p->lnext ,0 };
        }
        else if (ns.p->rnext != NULL && ns.state <2) {//节点未访问或只访问了左节点
            stk.push({ ns.p,2 });
            ns = { ns.p->rnext ,0 };
        }
        else {
            //如果左节点未访问,标记左节点被访问,当前节点入栈,移动到左节点;
            //如果左节点为空,从栈中取出节点作为当前节点(栈为空结束循环);
            //标记右节点被访问,当前节点入栈,移动到其右节点;
            //如果左、右节点皆为空或被访问,输出该节点。
            cout << ns.p->val; 
            if (!stk.empty()) {
                ns = stk.top();
                stk.pop();

            }
            else break;
        }
    }
}

4.按层遍历

//按层遍历
void layerTraversal(Node* head) {
    queue<Node*> que;
    que.push(head);
    while (!que.empty()) {
        Node* p = que.front();
        que.pop();
        cout << p->val;
        if (p->lnext != NULL) que.push(p->lnext);
        if (p->rnext != NULL) que.push(p->rnext);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值