数据结构 - 二叉树的遍历

本文深入解析二叉树的遍历方法,包括递归与非递归的前序、中序、后序遍历,以及广度优先遍历。通过实例代码演示了如何使用栈和队列实现非递归遍历,适合初学者掌握二叉树的基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程大家好!欢迎来到我的网站! 人工智能被认为是一种拯救世界、终结世界的技术。毋庸置疑,人工智能时代就要来临了,科… 继续阅读 前言https://www.captainai.net/troubleshooter

二叉树的遍历

N:访问根结点,L:遍历根结点的左子树,R:遍历根结点的右子树。

给定一棵二叉树的前序遍历序列和中序遍历序列可以惟一确定一棵二叉树。

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

深度优先遍历二叉树

1. 中序遍历(LNR)的递归算法:

若二叉树为空,则算法结束;否则:

中序遍历根结点的左子树;

访问根结点;

中序遍历根结点的右子树。

2. 前序遍历(NLR)的递归算法:

若二叉树为空,则算法结束,否则:

访问根结点;

前序遍历根结点的左子树;

前序遍历根结点的右子树。

3. 后序遍历(LRN)的递归算法:

若二叉树为空,则算法结束,否则:

后序遍历根结点的左子树;

后序遍历根结点的右子树;

访问根结点。

非递归深度优先遍历二叉树

栈是实现递归最常用的结构,利用一个栈来记下尚待遍历的结点或子树,以备以后访问,可以将递归的深度优先遍历改为非递归的算法。

1. 非递归前序遍历:遇到一个结点,就访问该结点,并把此结点推入栈中,然后下降去遍历它的左子树。遍历完它的左子树后,从栈顶托出这个结点,并按照它的右链接指示的地址再去遍历该结点的右子树结构。

2. 非递归中序遍历:遇到一个结点,就把它推入栈中,并去遍历它的左子树。遍历完左子树后,从栈顶托出这个结点并访问之,然后按照它的右链接指示的地址再去遍历该结点的右子树。

3. 非递归后序遍历:遇到一个结点,把它推入栈中,遍历它的左子树。遍历结束后,还不能马上访问处于栈顶的该结点,而是要再按照它的右链接结构指示的地址去遍历该结点的右子树。遍历完右子树后才能从栈顶托出该结点并访问之。另外,还需要给栈中的每个元素加上一个特征位,以便当从栈顶托出一个结点时区别是从栈顶元素左边回来的(则要继续遍历右子树),还是从右边回来的(则该结点的左、右子树均已遍历)。特征为Left表示已进入该结点的左子树,将从左边回来;特征为Right表示已进入该结点的右子树,将从右边回来。

非递归广度优先遍历二叉树

非递归广度优先遍历二叉树(层序遍历)是用队列来实现的。从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。

按照从根结点至叶结点、从左子树至右子树的次序访问二叉树的结点。算法如下:

1. 初始化一个队列,并把根结点入队列;

2. 当队列为非空时,循环执行步骤3到步骤5,否则执行6;

3. 出队列取得一个结点,访问该结点;

4. 若该结点的左子树为非空,则将该结点的左子树入队列;

5. 若该结点的右子树为非空,则将该结点的右子树入队列;

6. 结束。

/*
 * Binary Tree Breadth-First Traverse - by Chimomo
 */

#include <iostream>

#define _OK 1
#define _ERROR 0

using namespace std;

// Define node element type in binary tree.
typedef char Element;

// Binary tree node.
typedef struct BTNode {
    Element data;
    BTNode *lChild, *rChild; // Define left, right subtree.
} BTNode, *BTree;

// Define node element type in queue. (The node element type in queue is the pointer to binary tree node)
typedef BTNode *QElementType;
typedef int status;

// We need use queue to perform level traverse. So, define queue first.
typedef struct QNode {
    QElementType data;
    QNode *next;
} QNode, *QueuePtr;

// Definition of queue.
typedef struct {
    QueuePtr front;
    QueuePtr rear;
} LinkQueue;

status InitQueue(LinkQueue &Q) {
    Q.front = NULL;
    Q.rear = NULL;
    return _OK;
}

bool IsEmpty(LinkQueue Q) {
    return Q.front == NULL;
}

/**
 * Enqueue.
 * @param Q The queue.
 * @param e The queue element.
 * @return 1 for ok, 0 for error.
 */
status EnQueue(LinkQueue &Q, QElementType e) {
    // Construct queue node.
    QNode *ptrNode = (QNode *) malloc(sizeof(QNode));
    if (!ptrNode) {
        return _ERROR;
    }

    ptrNode->data = e;
    ptrNode->next = NULL;
    if (IsEmpty(Q)) {
        Q.front = Q.rear = ptrNode;
        return _OK;
    }

    Q.rear->next = ptrNode;
    Q.rear = ptrNode;
    return _OK;
}

/**
 * Dequeue.
 * @param Q The queue.
 * @param e The queue element.
 * @return 1 for ok, 0 for error.
 */
status DeQueue(LinkQueue &Q, QElementType &e) {
    if (IsEmpty(Q)) {
        return _ERROR;
    }

    QNode *tempPtr = Q.front;
    e = tempPtr->data;
    Q.front = tempPtr->next;
    free(tempPtr);
    return _OK;
}

/**
 * Create binary tree.
 * @param T The binary tree address.
 * @return 1 for success, 0 for fail.
 */
int CreateBTree(BTree &T) {
    char ch;
    cout << "Please input a character:" << endl;
    cin >> ch;
    if (ch == '#') {
        T = NULL;
    } else {
        // Allocate memory for new node.
        if (!(T = (BTNode *) malloc(sizeof(BTNode)))) {
            return 0; // Allocation fails.
        }

        T->data = ch;

        // Create left subtree.
        CreateBTree(T->lChild);

        // Create right subtree.
        CreateBTree(T->rChild);
    }

    return 1;
}

void VisitBTNode(BTNode *BT) {
    cout << BT->data << " ";
}

void VisitQNode(QNode *Q) {
    VisitBTNode(Q->data);
}

/**
 * Breadth-first traverse.
 * @param T The binary tree.
 */
void LevelTraverse(BTree T) {
    QElementType e;
    LinkQueue Q;
    InitQueue(Q);
    EnQueue(Q, T);
    while (!IsEmpty(Q)) {
        VisitQNode(Q.front);
        if (Q.front->data->lChild != NULL) {
            EnQueue(Q, Q.front->data->lChild);
        }
        if (Q.front->data->rChild != NULL) {
            EnQueue(Q, Q.front->data->rChild);
        }
        DeQueue(Q, e);
    }
}

int main() {
    BTree T;
    CreateBTree(T);
    cout << "Breadth-first traverse: ";
    LevelTraverse(T);
    return 0;
}

// Output:
/*
Please input a character:
1
1
Please input a character:
2
2
Please input a character:
3
3
Please input a character:
4
4
Please input a character:
5
5
Please input a character:
6
6
Please input a character:
#
#
Please input a character:
#
#
Please input a character:
#
#
Please input a character:
#
#
Please input a character:
#
#
Please input a character:
#
#
Please input a character:
#
#
Breadth-first traverse: 1 2 3 4 5 6
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值