【剑指offer】25.二叉树的下一个结点
总目录:
1.问题描述
给定一个二叉树其中的任意一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。
数据范围:节点数满足 1≤n≤50,节点上的值满足 1≤val≤100
要求:空间复杂度 O(1) ,时间复杂度 O(n)
输入:整体二叉树为{8,6,10,5,7,9,11},输入节点为8,按中序搜索的顺序,则返回值:9
输入:整体二叉树为{8,6,10,5,7,9,11},输入节点为6,按中序搜索的顺序,则返回值:7
2.问题分析
1递归
首先要清楚输入的节点是树上任意一个节点,
然后要清楚要找的是中序遍历顺序中目标节点的下一个节点,
因此需要先整树中序遍历到目标节点,然后继续遍历,借用等待标志位取下一个非空节点
2强行迭代
需要梳理出不同状况,层序分流,共分为四种情况
- 如果给出的结点有右子节点,则最终要返回的下一个结点即右子树的最左下的结点
- 如果给出的结点无右子节点,且当前结点是其父节点的左子节点,则返回其父节点
- 如果给出的结点无右子节点,且当前结点是其父节点的右子节点,则先要沿着左上方父节点爬树,一直爬到当前结点是其父节点的左子节点为止,返回的就是这个父节点;
- 或者没有满足上述情况的则返回为NULL
3.代码实例
递归
1 class Solution { 2 public: 3 bool isWaitting;//是否处于等待状态 4 TreeLinkNode* pTgtNode;//记录目标节点 5 TreeLinkNode* GetNext(TreeLinkNode* pNode) { 6 //空节点不予处理 7 if (!pNode) { 8 return NULL; 9 } 10 11 //标记目标节点和等待状态 12 pTgtNode = pNode; 13 isWaitting = false; 14 15 //获得整个树的根节点 16 TreeLinkNode* root = pNode; 17 while (root->next) { 18 root = root->next; 19 } 20 21 //整树搜索获得目标节点,搜索到后置为等待状态,等待下一个非空节点 22 return GetTarget(root); 23 } 24 25 TreeLinkNode* GetTarget(TreeLinkNode* root) { 26 //终止条件 27 if (!root) { 28 return NULL; 29 } 30 31 //中序遍历中先检查左侧 32 //先看左树是否符合 33 TreeLinkNode* pCur = NULL; 34 pCur = GetTarget(root->left); 35 if (pCur) { 36 return pCur; 37 } 38 39 //中序遍历的中 40 //是否在等待,如果在等立即将本节点返回 41 if (isWaitting) { 42 return root; 43 } 44 //是否要置起等待状态 45 if (root == pTgtNode) { 46 isWaitting = true; 47 } 48 49 //中序遍历的右 50 //查看右树是否符合 51 pCur = GetTarget(root->right); 52 if (pCur) { 53 return pCur; 54 } 55 56 return NULL; 57 } 58 };
迭代
1 class Solution { 2 public: 3 TreeLinkNode* GetNext(TreeLinkNode* pNode) { 4 // 如果有右子树 5 if(pNode->right) { 6 TreeLinkNode* rchild = pNode->right; 7 // 一直找到右子树的最左下的结点为返回值 8 while(rchild->left) rchild = rchild->left; 9 return rchild; 10 } 11 // 如果无右子树且当前结点是其父节点的左子结点 12 if(pNode->next && pNode->next->left == pNode) { 13 // 返回当前结点的父节点 14 return pNode->next; 15 } 16 // 如果无右子树且当前结点是其父节点的右子节点 17 if(pNode->next) { 18 TreeLinkNode* ppar = pNode->next; 19 // 沿着左上一直爬树,爬到当前结点是其父节点的左自己结点为止 20 while(ppar->next && ppar->next->right == ppar) ppar = ppar->next; 21 // 返回当前结点的父节点 22 return ppar->next; 23 } 24 return NULL; 25 } 26 };