前几天遇到一个笔试题,要求用非递归的方式实现一个二叉树的中序遍历,感觉还是挺有意思的一个算法题,当时的想法是仿照递归的原理构建一个节点指针的栈去实现,不过后来才发现里面有很多细节都需要注意,要考虑到处理各种结构的二叉树。
#include<stack> struct BinaryNode { int val; BinaryNode* left; BinaryNode* right; BinaryNode(int v=0) :val(v),left(nullptr), right(nullptr) {} void doSomething() { printf("node %d\n", val); } }; void inorderTraversal(BinaryNode* root) { std::stack<BinaryNode*>stkNodes; stkNodes.push(root); bool traceback = false;//标记当前的状况是否为“从子节点到父节点” while (!stkNodes.empty()) { BinaryNode* topNode = stkNodes.top(); if (topNode->left&&!traceback) {//如果上一次是从子节点回到父节点,则不能再把该节点的左子节点入栈 stkNodes.push(topNode->left); } else { topNode->doSomething(); stkNodes.pop();//节点访问完毕后,马上将该节点出栈 if (topNode->right) {//如有右子节点,入栈 stkNodes.push(topNode->right); traceback = false; } else { traceback = true;//遍历到了叶子节点,标记回溯状态 } } } }
测试:任意构建一棵二叉树,如图:
int main() { BinaryNode nodes[9]; for (int i = 0; i < 9; ++i) nodes[i] = BinaryNode(i); nodes[0].left = &nodes[1]; nodes[0].right = &nodes[2]; nodes[1].left = &nodes[3]; nodes[1].right = &nodes[4]; nodes[2].right = &nodes[5]; nodes[4].left = &nodes[6]; nodes[4].right = &nodes[7]; nodes[6].right = &nodes[8]; inorderTraversal(nodes); }
结果:
如有不对欢迎指正。