二叉树的前驱和后继
来源:互联网 发布: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&¤t==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&¤t==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
- 二叉树的前驱和后继
- 二叉树遍历的前驱和后继
- 二叉树遍历的前驱和后继规则说明
- 查找线索二叉树的前驱和后继
- [数据结构] 二叉搜索树 前驱和后继的经验总结
- 线索二叉树中查找前驱和后继的问题
- 树和二叉树4——前驱和后继
- 二叉查找树后继节点和前驱节点查找
- 二叉查找树后继节点和前驱节点查找
- 二叉查找树查找后继,前驱的问题
- 线索二叉树前驱后继的查询算法(C 语言)
- 二叉树前驱后继的查找(这个容易理解)
- 二叉树的线索化及其前驱后继查找
- 分析线索二叉树的前驱、后继求法
- 求二叉搜索树任一节点的前驱后继节点
- 关于二叉树遍历的前驱后继规则
- 算法导论-二叉树删除 前驱 后继
- 二叉线索树,寻找前驱与后继
- C++ 操作数据库类
- Count Primes
- 收藏的一些资源:包括Android sdk国内镜像,开发中涉及到的各种实用工具
- 欢迎使用Markdown编辑器写博客
- 交替的字符
- 二叉树的前驱和后继
- termios结构体以及串口应用
- Error: Trying to remove "yum", which is protected
- Eclipse项目移植配置
- PHP写入TXT
- 要看的重要书籍
- 程序员如何快速准备面试中的算法
- 修改springmvc的配置文件application-servlet
- 二叉树的中序遍历线索化