二叉树遍历的前驱和后继

    下面关于二叉树三种遍历方法的前驱和后继作讨论和总结。
一、前序遍历
1.1 找后继:  
  (1)若有左子女,则后继是左子女;
  (2)若无左子女,有右子女,则后继是右子女;
  (3)若既无左子女,又无右子女,则是一片叶子:
    a.若是其父母的左子女,且父母有右子女,则后继是父母的右子女。
    b.若是其父母的左子女,且父母无右子女;
    c.若是其父母的右子女。
    b、c都表示这是某个节点的左子树前序遍历的最后一个节点,则需要找第一个有右子树的“左祖先”(即找第一个使得当前节点在这个祖先的左子树上),然后后继就是这个祖先的右子女。
  如何找这个左祖先?即
  while( (p->parent->rchild==NULL||p->parent->rchild==p) && p!=NULL )
    p=p->parent;
  if(!p)表示已经全部遍历完毕。结束;else p=p->lchild;下一个节点
1.2 找前驱
  (1)若是父母的左孩子,则前驱是父母;
  (2)若是父母的右孩子,且父母无左子树,则前驱是父母;
  (3)若是父母的右孩子,父母有左子树,则前驱是父母左子树的最后访问到的节点(指向父母的左子树后,一直往右,若不行的话,往左一步,一直到叶子)
二、中序遍历
2.1 找后继
  (1)如有右子女,后继是右子女的最左下节点;
  (2)若无右子女,且是父母的左子女,则后继就是父母;
  (3)若无右子女,且是父母的右子女,则一直上溯到第一个“左祖先”(定义如前面)则后继就是这个祖先。若无这样的祖先,说明已经遍历完毕。
2.2 找前驱
  (1)如有左子女,前驱是左子女的最右下节点;
  (2)若无左子女,且是父母的右子女,则前驱就是父母;
  (3)若无左子女,且是父母的左子女,则一直上溯到第一个“右祖先”(定义如前面)则前驱就是这个祖先。若无这样的祖先,说明已经遍历完毕。
三、后序遍历
3.1 找后继
  (1)若是父母的右孩子,则后继是父母;
  (2)若是父母的左孩子,且父母无右子树,则后继是父母;
  (3)若是父母的左孩子,父母有右子树,则后继是父母右子树的最先访问到的节点(指向父母的右子树后,一直往左,若不行的话,往右一步,一直到叶子)
3.2 找前驱:  
  (1)若有右子女,则前驱是右子女;
  (2)若无右子女,有左子女,则前驱是左子女;
  (3)若既无左子女,又无右子女,则是一片叶子;再讨论:
    a.若是其父母的右子女,且父母有左子女,则前驱是父母的左子女。
    b.若是其父母的右子女,且父母无左子女;
    c.若是其父母的左子女。
    b、c都表示这是某个节点的右子树后序遍历的第一个节点,则需要找第一个
有    左子树的“右祖先”,然后前驱就是这个祖先的左子女。
  其实前序遍历是“左右根”,中序遍历是“左根右”,后序是“左右根”,我们可以看出,前序找后继和后序找前驱是对偶的(只要把左换成右,前驱换成后继,第一访换成最后访问即可),同样前序找前驱和后序找后继,中序找前驱和中序找后继都是对偶的,这样记忆起来就非常方便了~~~~~
    附上中序遍历查找前驱后后继的代码:

 
 
  1. typedef struct _node {    
  2.     struct _node *left_child;    
  3.     struct _node *right_child;    
  4.     struct _node * parent;  
  5.     ctype    data;    
  6. }node; //树节点数据结构定义  
  7.   
  8. typedef node* Tree;  
  9.   
  10. //查找二叉查找树中关键字最小的节点,返回指向该节点的指针  
  11. Tree tree_minimum(Tree root)  
  12. {  
  13.     Tree p = root;  
  14.     while (p->left_child != null)  
  15.         p = p->left_child;  
  16.     return p;  
  17. }  
  18.   
  19. //查找二叉查找树中关键字最大的节点,返回指向该节点的指针  
  20. Tree tree_maxmum(Tree root)  
  21. {  
  22.     Tree p = root;  
  23.   
  24.     while (p->right_child != null)  
  25.     {  
  26.         p = p->right_child;  
  27.     }  
  28.     return p;  
  29. }  
  30.   
  31. //查找二叉查找树中节点x的后继节点,返回指向该节点的指针  
  32. //在查找过程中,如果节点x右子树不为空,那么返回右子树的最小节点即可  
  33. //如果节点x的右子树为空,那么后继节点为x的某一个祖先节点的父节点,而且该祖先节点是作为其父节点的左儿子  
  34. Tree tree_successor(Tree x)  
  35. {  
  36.     if (x->right_child != null)  
  37.         return tree_minimum(x->right_child);  
  38.       
  39.     //x用来保存待确定的节点  
  40.     //y为x的父节点   
  41.     Tree y = x->parent;  
  42.   
  43.     while (y != NULL && x == y->right_child)  
  44.     {  
  45.         x = y;  
  46.         y = y->parent;  
  47.     }  
  48.     return y;  
  49. }  
  50.   
  51.   
  52. //查找二叉查找树中节点x的前驱节点,返回指向该节点的指针  
  53. //在查找过程中,如果节点x左子树不为空,那么返回左子树的最大节点即可  
  54. //如果节点x的左子树为空,那么前驱节点为x的某一个祖先节点的父节点,而且该祖先节点是作为其父节点的右儿子  
  55. Tree tree_predecessor(Tree x)  
  56. {  
  57.     if (x->left_child != null)  
  58.         return tree_maxmum(x->left_child);  
  59.   
  60.     Tree y = x->parent;  
  61.     while (y != NULL && x == y->left_child)  
  62.     {  
  63.         x = y;  
  64.         y = y->parent;  
  65.     }  
  66.     return y;  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值