软考
APP下载

二叉树的遍历非递归实现

二叉树是计算机科学中最常用的数据结构之一,它是由节点和边组成的,其中每个节点最多只有两个子节点。在二叉树中,有三种遍历方式:先序遍历、中序遍历和后序遍历。在实际的开发中,遍历二叉树是经常用到的操作之一。本文将从多个角度分析二叉树的遍历,并介绍如何通过非递归方式实现二叉树的遍历。

递归遍历

在了解非递归遍历之前,我们需要了解递归遍历。递归遍历是通过递归方式实现的,它的优点是实现简单,代码易于理解和维护。例如,先序遍历的递归实现如下:

```

void preOrderTraversal(TreeNode* root) {

if (root == nullptr) return;

cout << root->val << " ";

preOrderTraversal(root->left);

preOrderTraversal(root->right);

}

```

这段代码的逻辑很清晰,它会先输出当前节点的值,然后分别递归遍历左子树和右子树。中序遍历和后序遍历的递归实现也大致类似。虽然递归遍历方法简单,但是在遍历深度较大的二叉树时,递归会使得系统的栈空间被占用过多,有可能会导致栈溢出的问题。

非递归遍历

为了解决递归遍历的栈溢出问题,我们可以使用非递归方式实现二叉树的遍历。非递归遍历有多种实现方式,下面我们将分别介绍先序、中序、后序遍历的非递归实现方法。

先序遍历非递归实现

先序遍历的非递归实现方法使用栈来模拟递归调用的过程。首先将根节点入栈,然后在循环中不断取出栈顶元素进行操作。具体实现如下:

```

vector preOrderTraversal(TreeNode* root) {

vector res;

if (!root) return res;

stack st;

st.push(root);

while (!st.empty()) {

TreeNode* node = st.top();

st.pop();

res.push_back(node->val);

if (node->right) st.push(node->right);

if (node->left) st.push(node->left);

}

return res;

}

```

在这段代码中,我们需要维护一个栈,先将根节点入栈。然后在循环中,每次取出栈顶元素,先输出该节点的值,然后将右子节点和左子节点分别入栈,因为先序遍历的顺序是根节点、左子节点、右子节点。

中序遍历非递归实现

中序遍历的非递归实现方法也使用栈来模拟递归调用的过程。具体实现如下:

```

vector inorderTraversal(TreeNode* root) {

vector res;

stack st;

TreeNode* cur = root;

while (cur || !st.empty()) {

while (cur) {

st.push(cur);

cur = cur->left;

}

cur = st.top();

st.pop();

res.push_back(cur->val);

cur = cur->right;

}

return res;

}

```

在这段代码中,我们需要维护一个栈,首先将根节点的所有左子节点入栈。然后在循环中,每次取出栈顶元素,输出该节点的值,并将当前节点赋值为该节点的右子节点,继续进入下一个循环,将该节点的所有左子节点入栈,直到所有节点遍历完毕。

后序遍历非递归实现

后序遍历的非递归实现方法相对比较复杂,需要使用两个栈来实现。具体实现如下:

```

vector postorderTraversal(TreeNode* root) {

vector res;

if (!root) return res;

stack st1, st2;

st1.push(root);

while (!st1.empty()) {

TreeNode* node = st1.top();

st1.pop();

st2.push(node);

if (node->left) st1.push(node->left);

if (node->right) st1.push(node->right);

}

while (!st2.empty()) {

TreeNode* node = st2.top();

st2.pop();

res.push_back(node->val);

}

return res;

}

```

在这段代码中,我们需要维护两个栈,首先将根节点入栈1。然后在循环中,每次取出栈1的栈顶元素,将该节点入栈2,并将该节点的左子节点和右子节点分别入栈1。这样在栈2中,所有的节点遍历顺序是先右子节点、再左子节点、最后根节点。

接下来,只需要遍历栈2即可得到后序遍历的结果。

结语

本文从递归和非递归遍历两个角度分析了二叉树的遍历方法,并详细介绍了先序、中序和后序遍历的非递归实现方法。通过使用栈来模拟递归调用的过程,可以有效避免递归造成的栈溢出问题。总体而言,非递归遍历方法具有效率高、速度快的优点,是二叉树遍历的常用实现方式。

备考资料 免费领取:软件设计师报考指南+考情分析+思维导图等 立即下载
真题演练 精准解析历年真题,助你高效备考! 立即做题
相关阅读
软件设计师题库