二叉树的中序遍历,时间复杂度为O(N),空间复杂度为O(1)。
这种遍历就是Morris遍历。这种遍历的实质是避免使用栈结构,而是让下层到上层有指针,具体是通过让底层节点指向nullptr的空闲指针指回上层的某个节点,从而完成下层到上层的移动。
可分为两个步骤:
- 第一步骤
- 设当前字数的头结点为HeadNode,让HeadNode的左子树中最右节点的right指针指向HeadNode,
- 然后HeadNode的左子树继续执行步骤1的处理过程,直至遇到某一个节点没有左子树时记为Node,进入下一步骤
- 第二步骤
- 从Node开始通过每个节点的right指针进行移动,并且依次打印。设移动到的节点为curNode,对每个curNode节点都进行判断curNode节点的左子树中最右节点是否指向curNode
- 如果指向,将最右节点的right指针指向nullptr(恢复树的原状),打印curNode,继续通过curNode的right指针移动到下一个节点,重复第二步骤
- 如果没有,以curNode为头的子树执行第一步骤。
我们可以通过下面的图片展示的过程来理解上面两个步骤
代码验证:
#include<iostream>
using namespace std;
struct TreeNode{
TreeNode* left;
TreeNode* right;
char value;
};
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
TreeNode* BinaryTreeCreate(char* a, int* Index)
{
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
if (a[*Index] == '#')
return NULL;
root->value = a[*Index];
++(*Index);
root->left = BinaryTreeCreate(a, Index);
++(*Index);
root->right = BinaryTreeCreate(a, Index);
return root;
}
void inorderTraversal(TreeNode* root)
{
if (root == nullptr)
{
return;
}
TreeNode* Node1 = root;
TreeNode* Node2 = nullptr;
while (Node1 != nullptr)
{
//指向左子树
Node2 = Node1->left;
if (Node2 != nullptr)
{
//找左子树的最右节点
while (Node2->right != nullptr&&Node2->right != Node1)
{
Node2 = Node2->right;
}
//如果最右节点指向空,将最右节点的右指针指向Node1(即该子树的根节点)
if (Node2->right == nullptr)
{
Node2->right = Node1;
Node1 = Node1->left;
continue;
}
else
{
//(Node2->right == Node1)
//如果最右节点的右指针指向Node1,即将该子树遍历完毕,将右指针指向nullptr(恢复原状)
Node2->right = nullptr;
}
}
//cout << (Node1->value) << " " << endl;
printf("%c ", Node1->value);
Node1 = Node1->right;
}
cout << endl;
}
int main()
{
char* a = "ABD##E#H##CF##G##";
int Index = 0;
TreeNode* root = BinaryTreeCreate(a, &Index);
inorderTraversal(root);
return 0;
}