话不多说,前两种直接上代码:
递归方法:
void preOrder(TreeNode* root){
if(root != NULL){
preOrder(root->left);
cout << root->val << " ";
preOrder(root->right);
}
}
循环方法:
void preOrder(TreeNode* root){
if(root == NULL) return;
stack<TreeNode*> S;
TreeNode* node = root;
while(node!=NULL || !S.empty()){
if(node != NULL)}{
// cout << node->val << " "; 先序遍历:在push时访问结点值
S.push(node);
node = node->left;
}
else{
cout << node->val << " "; // 中序遍历:在弹出栈顶指针时访问
node = S.top()->right;
S.pop();
}
}
}
上述两种方法,时间复杂度为O(nlgn),空间复杂度为O(n)
优化空间复杂度为O(1)的方法:利用线索二叉树的概念
如果不能用栈空间,一个明显的问题是:如何返回到父节点。
线索二叉树利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以。
步骤如下:
1. 如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。 a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点(Cur)更新为当前节点的左孩子
注意(不是改变节点内容,而是把游标Cur继续行进到左孩子)。 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)
{
cout<<cur->val;
cur=cur->right;
}
else
{
pre=cur->left;
while(pre->right!=NULL&&pre->right!=cur)
pre=pre->right;
if(pre->right==NULL)
{
pre->right=cur;
cur=cur->left;
}
else
{
pre->right=NULL;
cout<<cur->val;
cur=cur->right;
}
}
}
}