【中序线索二叉树】
前驱结点
对于中序线索二叉树来说,当给出指定结点 p
,要找到其中序前驱结点 pre
,可按照如下步骤:
- 若
p->ltag=1
,说明进行了线索化,那么pre=p->lchild
- 若
p->ltag=0
,说明其必有左孩子,那么pre
为p
的左子树中最右下结点
1 | ThNode *findPreByInThreadTree(ThNode *p) { //中序线索二叉树找前驱 |
后继结点
对于中序线索二叉树来说,当指定结点 p
,要找到其中序后继结点 post
,可按照如下步骤:
- 若
p->rtag=1
,说明进行了线索化,那么post=p->rchild
- 若
p->rtag=0
,说明其必有右孩子,那么post
为p
的右子树中最左下结点
1 | ThNode *findPostByInThreadTree(ThNode *p) { //中序线索二叉树找后继 |
【前序线索二叉树】
前驱结点
对于前序线索二叉树来说,当指定结点 p
,要找到其前序前驱结点 pre
,可按照如下步骤:
- 若
p->ltag=1
,说明进行了线索化,那么post=p->lchild
- 若
p->ltag=0
,说明没有进行线索化,此时p
的前驱与p
的父结点有关,因此只能从头开始遍历
为克服上述问题,一般采用三叉链表线索化的来建立前序线索二叉树,这样一来,可以很容易的找到其前驱:
- 若
p->ltag=1
,说明进行了线索化,那么post=p->lchild
- 若
p->ltag=0
,说明没有进行线索化,此时根据三叉链表的parent
指针,寻找p
的父结点:- 若能找到
p
的父结点,且p
是左孩子,那么p
的父结点即为前驱 - 若能找到
p
的父结点,且p
是右孩子,左兄弟为空,那么p
的父结点即为前驱 - 若能找到
p
的父结点,且p
是右孩子,左兄弟非空,那么p
的左兄弟子树中最后一个被先序遍历的点即为前驱 - 若不能找到
p
的父结点,即p
是根结点,则p
没有前序前驱
- 若能找到
后继结点
对于前序线索二叉树来说,当指定结点 p
,要找到其前序后继结点 post
,可按照如下步骤:
- 若
p->rtag=1
,说明进行了线索化,那么post=p->rchild
- 若
p->rtag=0
,说明没有进行线索化,必有右孩子,那么post
为p
的子树中第一个被先序遍历的结点- 若
p
有左孩子,则先序后继为左孩子 - 若
p
没有左孩子,则先序后继为右孩子
- 若
1 | ThNode *findPostByPreThreadTree(ThNode *p) { //前序线索二叉树找后继 |
【后序线索二叉树】
前驱结点
对于后序线索二叉树来说,当指定结点 p
,要找到其后序前驱结点 pre
,可按照如下步骤:
- 若
p->ltag=1
,说明进行了线索化,那么pre=p->lchild
- 若
p->ltag=0
,说明没有进行线索化,必有左孩子,那么pre
为p
的子树中最后一个被后序遍历的结点- 若
p
有右孩子,则前驱为p
的右孩子 - 若
p
没有右孩子,则前驱为p
的左孩子
- 若
1 | ThNode *findPreByPostThreadTree(ThNode *p) { //后序线索二叉树找前驱 |
后继结点
对于后序线索二叉树来说,当指定结点 p
,要找到其后序后继结点 post
,可按照如下步骤:
- 若
p->rtag=1
,说明进行了线索化,那么post=p->rchild
- 若
p->rtag=0
,说明没有进行线索化,此时p
的左右结点只可能是其前驱,p
的后继与p
的父结点有关,因此只能从头开始遍历
为克服上述问题,一般采用三叉链表线索化的来建立后序线索二叉树,这样一来,可以很容易的找到其后继:
- 若
p->rtag=1
,说明进行了线索化,那么post=p->rchild
- 若
p->rtag=0
,说明没有进行线索化,此时根据三叉链表的parent
指针,寻找p
的父结点:- 若能找到
p
的父结点,且p
是右孩子,则p
的父结点为其后继 - 若能找到
p
的父结点,且p
是左孩子,其右兄弟为空,则p
的父结点为其后继 - 若能找到
p
的父结点,且p
是左孩子,其右兄弟非空,则p
的右兄弟子树中第一个被后序遍历的结点为其后继 - 若不能找到
p
的父结点,即p
是根结点,则p
没有后序后继
- 若能找到