目录
一、思路
迭代法需要借助while循环和迭代栈。
中序遍历的顺序:左-根-右
遍历步骤:
1.准备一个当前指针cur,指向根结点;
2.开辟一个空的迭代栈;
3.进入while循环。循环结束的条件是:当前指针为空并且迭代栈为空。
因为当前指针不为空,迭代栈为空的情况是:根结点还未入栈
当前指针为空,迭代栈不为空的情况是:当前指针指向了目前最左元素的左孩子,而这个孩子肯定是nullptr
4.在大循环中,首先建立一个小循环,不断地将当前指针指向的结点入栈,然后当前指针指向这个结点的左孩子;
5.由于4中,当前指针肯定最终指向空,所以让当前指针指向栈顶元素,此时栈顶元素即为应该遍历的元素;
6.栈顶元素入结果集后,出栈,再让其右孩子入栈,因为肯定已经遍历完成了当前子树的左和根;
7.重复上述操作
二、举例
假设有这样一颗树:
1.根结点入栈
2.不断让左孩子入栈
3.弹出栈顶元素,让其右孩子入栈
4.重复上述操作,直到当前指针为空且栈为空
三、代码
核心代码:
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> ans;
stack<TreeNode*> s;
TreeNode* cur = root;
//当前结点不为空或者栈不为空
//也就是说,循环结束条件是:
//当前结点为空且栈为空
while (cur != nullptr || !s.empty())
{
//如果当前结点不为空,那么就放入栈,
//然后当前指针指向其左孩子结点
if (cur != nullptr)
{
s.push(cur);
cur = cur->left;
}
//如果当前结点为空,说明已经到目前最左的尽头,
//那么指向栈顶元素
//此时的栈顶元素为以当前结点为根的子树的根
//其左孩子因为已经为空,所以目前遍历根
//遍历完后再让当前指针指向其右孩子结点
else
{
cur = s.top();
s.pop();
ans.push_back(cur->val);
cur = cur->right;
}
}
return ans;
}
测试用例:
int main()
{
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->val = 3;
TreeNode* n1 = (TreeNode*)malloc(sizeof(TreeNode));
n1->val = 4;
TreeNode* n2 = (TreeNode*)malloc(sizeof(TreeNode));
n2->val = 5;
TreeNode* n3 = (TreeNode*)malloc(sizeof(TreeNode));
n3->val = 6;
TreeNode* n4 = (TreeNode*)malloc(sizeof(TreeNode));
n4->val = 7;
TreeNode* n5 = (TreeNode*)malloc(sizeof(TreeNode));
n5->val = 8;
TreeNode* n6 = (TreeNode*)malloc(sizeof(TreeNode));
n6->val = 9;
root->left = n1;
root->right = n2;
n1->left = n3;
n1->right = n4;
n2->left = n5;
n2->right = n6;
n3->left = nullptr;
n3->right = nullptr;
n4->left = nullptr;
n4->right = nullptr;
n5->left = nullptr;
n5->right = nullptr;
n6->left = nullptr;
n6->right = nullptr;
vector<int> v = inorderTraversal(root);
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
return 0;
}
运行截图: