【中序线索二叉树】
前驱结点
对于中序线索二叉树来说,当给出指定结点 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没有后序后继
- 若能找到