二叉树线索化
二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息
n个节点的二叉树中含有n+1个空指针域。利用二叉树中的空指针域 来存放在某种遍历次序下的前驱和后继 ,这种指针叫“线索”。这种加上了线索的二叉树称为线索二叉树。
前序遍历
void noSpacePre(TreeNode * root)
{
TreeNode * pCur=root;
TreeNode * plast=NULL;
while(pCur)
{
if(pCur->left)
{
plast=pCur->left;
while(plast->right && plast->right!=pCur)
{
plast=plast->right;
}
if(plast->right==NULL)
{
plast->right=pCur;
cout<<pCur->val<<" ";
pCur=pCur->left;
}
else
{
plast->right=NULL;
pCur=pCur->right;
}
}
else
{
cout<<pCur->val<<" ";
pCur=pCur->right;
}
}
}
中序遍历
void noSpaceInorder(TreeNode * root)
{
TreeNode * plast=NULL;
TreeNode *pCur=root;
while(pCur)
{
if(pCur->left==NULL)
{
cout<<pCur->val<<" ";
pCur=pCur->right;
}
else
{
plast=pCur->left;
while(plast->right && plast->right!=pCur)
{
plast=plast->right;
}
if(plast->right==NULL)
{
plast->right=pCur;
pCur=pCur->left;
}
else
{
plast->right=NULL;
cout<<pCur->val<<" ";
pCur=pCur->right;
}
}
}
}
后序遍历
后续遍历稍显复杂,需要建立一个临时节点dump,令其左孩子是root。并且还需要一个子过程,就是倒序输出某两个节点之间路径上的各个节点。
步骤:
当前节点设置为临时节点dump。
-
如果当前节点的左孩子为空,则将其右孩子作为当前节点。
-
如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。
a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。
b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空。倒序输出从当前节点的左孩子到该前驱节点这条路径上的所有节点。当前节点更新为当前节点的右孩子。
-
重复以上1、2直到当前节点为空。
参考文章:https://blog.youkuaiyun.com/zuochao_2013/article/details/78538729
void reverseEdge(TreeNode * &node)
{
TreeNode * last = NULL;
TreeNode * next = node->right;
while (next)
{
node->right = last;
last = node;
node = next;
next = next->right;
}
node->right = last;
}
void printEdge(TreeNode* &node)
{
reverseEdge(node);
TreeNode * next = node->right;
TreeNode * last = NULL;
while (next)
{
cout << node->val << " ";
node->right = last;
last = node;
node = next;
next = next->right;
}
cout << node->val << " ";
node->right = last;
}
void morrisPostorder(TreeNode * root)
{
TreeNode* preRoot = new TreeNode(-1);
preRoot->left = root;
TreeNode *pCur = preRoot;
TreeNode *pPrev = NULL;
while (pCur)
{
if (pCur->left)
{
pPrev = pCur->left;
while (pPrev->right && pPrev->right != pCur)
{
pPrev = pPrev ->right;
}
if (pPrev->right == NULL)
{
pPrev->right = pCur;
pCur = pCur->left;
}
else
{
pPrev->right = NULL;
printEdge(pCur->left);
pCur = pCur->right;
}
}
else
{
pCur = pCur->right;
}
}
}