二叉树的前驱和后继

来源:互联网 发布:vfp编程入门 编辑:程序博客网 时间:2024/04/27 14:36

前提

二叉树的几何结构和遍历路径,是查找前驱和后继的基础。

结点分类

几何结构千变万化,但单个结点必然和至多3点邻接:左(或右)父,左子和右子。按照“X”型助记,交叉点为研究对象。为求结点N的前驱结点Pre和后继结点Suc,设N的左子lchild,右子rchildm,N的左父亲lparent,右父亲rparent;
二叉树的结构

先后顺序

同一几何结构,不同的遍历方式得到不同的遍历路径;具体到单个结点,也就有不同的前驱结点和后继结点。

定义的二叉树数据结构(C++)

template<typename T> struct BNode{    T m_data;    BNode<T>* rchild;    BNode<T>* lchild;    BNode<T>* parent;    int ltag;    int rtag;    BNode(T data=0):m_data(data),rchild(NULL),lchild(NULL),parent(NULL),ltag(0),rtag(0){}};template<typename T> struct BTree{    BNode<T>* m_root;    BNode<T>* index;    BNode<T>* pre;    T m_data;    BTree(BNode<T>* root=NULL,T data=0):m_root(root),m_data(data),pre(NULL){}}

具体讨论

4.1 先序遍历
先序前驱与后序后继,先序后继与后续前驱,和中序前驱与中序后继,分别形成3对镜像过程。
4.1.1 先序前驱
这里写图片描述

  • 若当前节点拥有右父亲节点,则Pre=node->parent;
  • 若当前节点拥有左父亲节点,且父亲节点左子树为空,则Pre=node->parent;
  • 若当前节点拥有左父亲节点,且父亲节点左子树不为空,则Pre等于父亲节点左子树的最右的末节点(至右至左);
T get_pre_pre(BNode<T>* root)//先序遍历的前驱节点{    if(root==NULL)    {        return 0;    }    BNode<T>* father=root->parent;    if(!father)    {        return 0;    }    if(root==father->lchild)    {        return father->m_data;    }    else if(root==father->rchild)    {        if(!father->lchild)        {            return 0;        }        BNode<T>* child=father->lchild;        while(child->rchild||child->lchild)        {            while(child->rchild)            {                child=child->rchild;            }            while(child->lchild)            {                child=child->lchild;            }        }        return child->m_data;    }}

4.1.2 先序后继
这里写图片描述

  • 若左孩子不为空,Suc=root->lchild;
  • 若左孩子为空,且右孩子不为空,则Suc=root->rchild;
  • 若左右子树都为空,且有右父亲节点,则后继为最近的右父祖先的右子树的头节点;
T get_pre_suc(BNode<T>* root)// 先序遍历的后继节点,比较特殊四种情况都可以{    if(root==NULL)    {        return 0;    }    if(root->lchild)    {        return root->lchild->m_data;    }    else if(root->rchild)    {        return root->rchild->m_data;    }    else if(root->parent&&root==root->parent->lchild)    {        BNode<T>* father=root->parent;        if(!father->rchild)        {            return 0;        }        return father->rchild->m_data;    }    else if(root->parent&&root==root->parent->rchild)    {        BNode<T>* father=root->parent;        BNode<T>* current=root;        while(father&&current==father->rchild)        {            current=father;            father=father->parent;        }        if(!father->rchild)        {            return 0;        }        return father->rchild->m_data;    }}

4.2 中序遍历
4.2.1 中序前驱
这里写图片描述

  • 若左子树不为空root->lchild!=NULL,则Pre=左子树的最右的叶子节点;
  • 若左子树为空,且拥有左父亲节点,则Pre=左父亲节点;
  • 若左子树为空,且拥有右父亲节点,则Pre=最近的左父祖先节点;
T get_pre(BNode<T>* root)/*查找一个中序遍历二叉树节点的前驱节点*/{    if(root==NULL)    {        return 0;    }    if(root->lchild)    {        BNode<T>* start=root->lchild;        while(start->rchild)        {            start=start->rchild;        }        return start->m_data;    }    else if(root->parent)    {        BNode<T>* father=root->parent;        BNode<T>* current=root;        while(father&&father->lchild==current)        {            current=father;            father=father->parent;        }        if(father)        {            return father->m_data;        }        return 0;    }}

4.2.2 中序后继
这里写图片描述

  • 若右子树不为空root->rchild!=NULL,则Suc=右子树最左的叶子节点;
  • 若右子树为空,且拥有右父亲节点,则Suc=右父亲节点;
  • 若右子树为空,且拥有左父亲节点,则Suc=最近的右祖先节点;
T get_suc(BNode<T>* root)/*查找一个中序遍历二叉树节点的后继节点*/{    if(root==NULL)    {        return 0;    }    if(root->rchild)    {        BNode<T>* right=root->rchild;        while(right->lchild)        {            right=right->lchild;        }        return right->m_data;    }    else if(root->parent)    {        BNode<T>* father=root->parent;        BNode<T>* current=root;        while(father&&father->rchild==current)        {            current=father;            father=father->parent;        }        if(father)        {            return father->m_data;        }        return 0;    }}

4.3 后序遍历

4.3.1 后序前驱
这里写图片描述

  • 若右孩子不为空,则Pre=root->rchild;
  • 若右孩子为空,左孩子不为空,则Pre=root->lchild;
  • 若左右孩子都为空,则Pre=最近的左祖先的左子树的头节点
T get_post_pre(BNode<T>* root)//获取后序遍历的前驱节点{    if(!root)    {        return 0;    }    if(root->rchild)    {        return root->rchild->m_data;    }    else if(root->lchild)    {        return root->lchild->m_data;    }    else if(root->parent)    {        BNode<T>* father=root->parent;        BNode<T>* current=root;        while(father&&current==father->lchild)        {            current=father;            father=father->parent;        }        if(father&&father->lchild)        {            return father->lchild->m_data;        }        return 0;    }    return 0;}

4.3.2 后序后继
这里写图片描述

  • 若拥有左父亲节点,则Suc=左父亲节点
  • 若拥有右父亲节点,且父亲右子树为空,则Suc=右父亲节点;
  • 若拥有右父亲节点,且父亲右子树不为空,则Suc=父亲右子树的最左的左孩子节点;
T get_post_suc(BNode<T>* root)// 获取后序遍历的后继节点{    if(!root||!root->parent)    {        return 0;    }    if(root==root->parent->rchild)    {        return root->parent->m_data;    }    else if(root==root->parent->lchild&&!root->parent->rchild)    {        return root->parent->m_data;    }    else if(root==root->parent->lchild&&root->parent->rchild)    {        BNode<T>* start=root->parent->rchild;        while(start->lchild||start->rchild)        {            while(start->lchild)            {                start=start->lchild;            }            while(start->rchild)            {                start=start->rchild;            }        }        return start->m_data;    }    return 0;}

代码测试

  • 测试二叉树图
    这里写图片描述
  • 测试结果
pre order -------------------current data: 8  pre: 0  post: 6current data: 6  pre: 8  post: 5  father node data: 8current data: 5  pre: 6  post: 7  father node data: 6current data: 7  pre: 5  post: 10  father node data: 6current data: 10  pre: 7  post: 9  father node data: 8current data: 9  pre: 10  post: 12  father node data: 10current data: 12  pre: 9  post: 11  father node data: 10current data: 11  pre: 12  post: 0  father node data: 12in order -------------------current data: 5  pre: 0  post: 6  father node data: 6current data: 6  pre: 5  post: 7  father node data: 8current data: 7  pre: 6  post: 8  father node data: 6current data: 8  pre: 7  post: 9current data: 9  pre: 8  post: 10  father node data: 10current data: 10  pre: 9  post: 11  father node data: 8current data: 11  pre: 10  post: 12  father node data: 12current data: 12  pre: 11  post: 0  father node data: 10postorder -------------------current data: 5  pre: 0  post: 7  father node data: 6current data: 7  pre: 5  post: 6  father node data: 6current data: 6  pre: 7  post: 9  father node data: 8current data: 9  pre: 6  post: 11  father node data: 10current data: 11  pre: 9  post: 12  father node data: 12current data: 12  pre: 11  post: 10  father node data: 10current data: 10  pre: 12  post: 8  father node data: 8current data: 8  pre: 10  post: 0/*0表示没有前驱或者后继或者父亲节点*/
0 0
原创粉丝点击