二叉树的中序遍历(递归和循环)使数据结构的一种基本知识,不做过多解释了,直接附上代码。
递归:
void pre(TreeNode* root){//中序递归遍历 if(root != NULL){ pre(root->left); cout << root->val << " "; pre(root->right); } }
循环:
void pre(TreeNode* root){ if(root == NULL) return; stack<TreeNode*>p; TreeNode* node = root; while(node!=NULL || !p.empty()){ if(node != NULL)}{ p.push(node); node = node->left; } else{ node = p.top(); p.pop(); cout << node->val << " "; // 中序遍历:在弹出栈顶指针时访问 node = node->right; } }
上述两个方法的空间复杂度均为O(nlogn).
优化空间复杂度为O(1)的方法:利用线索二叉树的概念
线索二叉树利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以。
步骤如下:
1. 如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。
a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。
b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。
3. 重复以上1、2直到当前节点为空。
图示:
下图为每一步迭代的结果(从左至右,从上到下),cur代表当前节点,深色节点表示该节点已输出。
图片和步骤来源:https://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html
void recoverTree(TreeNode *root)///这里是采用O(1)的算法
{
if(root==NULL)
return;
TreeNode* pre=NULL;
TreeNode* cur=root;
while(cur)
{
if(cur->left==NULL)//步骤1
{
cout<<cur->val;
cur=cur->right;
}
else
{
pre=cur->left;
while(pre->right!=NULL&&pre->right!=cur)
pre=pre->right;
if(pre->right==NULL)//2.a
{
pre->right=cur;
cur=cur->left;
}
else//2.b
{
pre->right=NULL;
cout<<cur->val;
cur=cur->right;
}
}
}
}