二叉树的下一个结点:最直观的想法是,首先保存给定结点所对应的值pval,然后利用next指针找到二叉树的根节点Node,再使用双指针法与递归进行中序遍历,当前驱指针pre指向pval所对应的结点时,则使用result记录所求结果,其指向的即为二叉树的下一个结点。如果dfs设置返回值反而不太方便,所以将pre和result作为参数传递给函数,但是由于指针变量也是变量,又需要在函数内部更改这两个变量的值,故使用这两个变量的引用。
void dfs(TreeLinkNode* root, int pval, TreeLinkNode* &pre,TreeLinkNode*& result) { if (root == nullptr) return; dfs(root->left, pval, pre, result); //左 if (pre && pre->val == pval) //中 result = root; pre = root; dfs(root->right, pval, pre, result); //右 } TreeLinkNode* GetNext(TreeLinkNode* pNode) //pNode指向的是待找节点 { int pval = pNode->val; TreeLinkNode* Node = pNode; while (Node->next) //寻找根节点 Node = Node->next; TreeLinkNode* pre = nullptr; TreeLinkNode* result=nullptr; dfs(Node, pval, pre, result); return result; }
优化:上述中序遍历是遍历了整个二叉树,我们可以利用中序遍历中当前结点的下一个结点的规律,即如果当前结点的右子树不为空,那么下一个结点是右子树的最左下,反之如果当前结点的右子树为空,那么下一个结点是当前结点的第一个右父结点,前者可以使用循环实现,后者可以使用双指针实现。
TreeLinkNode* GetNext(TreeLinkNode* pNode) { TreeLinkNode *p=pNode->right; TreeLinkNode *q=NULL,*r=NULL; if(p!=NULL) //右子树不为空则下一个节点为右子树的最左下 { while(p&&p->left) p=p->left; return p; } else //右子树为空则下一个节点为第一个右父节点 { q=pNode->next; r=pNode; while(q&&q->right==r) { r=q; q=q->next; } return q; } return NULL; }
最后补充:一般二叉树类型的题目中都是给定参数为二叉树的根结点,但是可能代码接口中的输入看着很迷糊,其意思是pNode是给定的当前结点,这是整个完整的二叉树的一部分,我们可以根据该结点找到二叉树的根结点。