二叉树的层序遍历:栈与队列方式

二叉树有先序、中序和后序三种遍历方式外,还有第四种遍历方式:层序遍历。在说二叉树层序遍历前,我们先来了解以下对于二叉树的遍历的一些东西。对二叉树的遍历,二叉树每个结点都要有左子树和右子树(无论有无左右子树,遍历时都要会去检查),就像一个二维数组一样,二维数组每个数组元素都有两个数据。对于这些二位结构的数据结构遍历,最终遍历出来都会按照一条一维的线性序列。根据遍历方法的不同,产生的一维线性序列也就不同。那么对于二叉树这种二维结构来说,我们遍历二叉树时,访问了第一个结点,接着就要通过这个结点来访问左子树和右子树。所以每次遍历时,访问到一个结点,就要保存起来,防止当你遍历左子树时,找不回根节点,导致右子树遍历不了的情况。那么遍历时我们如何保存结点?我们需要一个存储结构来保存暂时不需要访问的结点,可以选择用栈或队列的方式。

用队列的方式,思路是:

1、遍历到一个结点A,该结点A入队。

2、结点A出队,该结点的左子树B和右子树C依次入队。

3、左子树结点B出队,左子树结B点的左右子树入队。

4、右子树结点C出队,右子树结点C的左右子树入队。

拿下面这个二叉树来举例:

一开始把A结点入队列,接着访问A结点,访问完后抛出A结点,然后把A结点的左右子树BC入队列。接着循环,在队列里面抛出第一个元素B,访问B,然后把B的左右子树DF入队列。重复循环,到把队列里的第一个元素C抛出来,C的左右子树GI入队列。我们可以看出,当C被抛出后,该二叉树的第二层被遍历完了,队列里存放的是第三层的结点。所以这样也就实现了队二叉树的一层一层的遍历。

这样的程序实现过程代码可以这样写:

52-55行创建一个队列和一个树结点,56行把树的根结点入队列,然后开始遍历。抛出根结点,然后访问输出它的Data,接着判断该根结点的左右子树,有就把它们入队列,从左子树到右子树的顺序。最后循环步骤。得出的遍历顺序肯定就是ABCDFGIEH

至于用栈的方式实现层序遍历,方法基本一样。也是先根结点入栈,然后根结点出栈,左右子树入栈,只是出栈时,队列是从左子树先出列再到右子树出列,而栈的方式至于遍历顺序反过来右子树先出栈再到左子树出栈即可。存储数据方式和出栈按照栈方式即可。对于层序遍历的函数依旧和上面的一样,下面附上栈的入栈和出栈函数:


  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,二叉树的遍历有三种主要方式:先序遍历(根-左-右)、中序遍历(左-根-右)和后序遍历(左-右-根)。非递归的层次遍历(也叫广度优先遍历,从上到下、从左到右)通常使用队列来辅助实现。 这里分别给出这些遍历的非递归算法代码: 1. 层序遍历(广度优先遍历): ```c #include <stdio.h> #include <stdlib.h> #include <queue> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void levelOrder(struct TreeNode* root) { if (root == NULL) return; // 使用队列存储每一层的节点 queue<struct TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; i++) { struct TreeNode* node = q.front(); q.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->left != NULL) q.push(node->left); if (node->right != NULL) q.push(node->right); } printf("\n"); // 换行表示新的一层 } } ``` 2. 先序遍历(递归和非递归两种方式,这里是非递归版本,使用栈): ```c void preorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; s.push(root); while (!s.empty()) { struct TreeNode* node = s.top(); s.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->right != NULL) s.push(node->right); if (node->left != NULL) s.push(node->left); } } ``` 3. 中序遍历(非递归,同样使用栈): ```c void inorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; struct TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); printf("%d ", curr->val); // 打印当前节点值 curr = curr->right; } } ``` 4. 后序遍历(非递归,使用两个): ```c void postorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { struct TreeNode* node = s1.top(); s1.pop(); s2.push(node); if (node->left != NULL) s1.push(node->left); if (node->right != NULL) s1.push(node->right); } while (!s2.empty()) { struct TreeNode* node = s2.top(); s2.pop(); printf("%d ", node->val); // 打印当前节点值 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值