二叉树后继
如果有指向父亲的结点,则:
1.如果当前结点有右儿子,或者当前结点是根结点,则后继结点为右子树的最左叶节点;
2.否则,如果当前结点是父结点的左儿子,则后继结点就是父结点;(其实是第三种情况的一个特例,即自己是第0代祖先,返回第一代祖先)
3.否则,向上遍历,直到n-1代祖先是n代祖先的左儿子,则后继结点为n代祖先;或者遍历到根节点后未找到符合的n代结点,则该结点为中序遍历的最后结点,没有后继。
时间复杂度为树的高度O(lgN)。
struct TreeNode
{
char key;
TreeNode *left;
TreeNode *right;
TreeNode *parent;
};
TreeNode *FindSuccessor(TreeNode *x)
{
if(x->right!=NULL)
{
TreeNode *q=x->right;
while(q->left)
q=q->left;
return q;
}
TreeNode *p=x->parent;
while(p&&x==p->right)
{
x=p;
p=p->parent;
}
return p;
}
如果没有父指针,则通过栈来实现中序遍历:
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
class Successor {
public:
int findSucc(TreeNode *root,int p){
stack<TreeNode *> st;
bool isFound=false;
TreeNode *cur=root;
while(cur||!st.empty()){
if(cur!=NULL){
st.push(cur);
cur=cur->left;
} else {
cur=st.top();st.pop();
if(isFound==true)return cur->val;
if(cur->val==p)isFound=true;
cur=cur->right;
}
}
return -1;
}
};
也可以通过递归实现:
class Successor {
public:
int findSucc(TreeNode* root, int p) {
// write code here
bool sign=0;
return findSucc1(root,p,sign);
}
int findSucc1(TreeNode* root,int p,bool &sign)
{
if(root==NULL)
return -1;
int left=findSucc1(root->left,p,sign);
if(left!=-1)
return left;
if(sign==true)
return root->val;
if(root->val==p)
sign=true;
return findSucc1(root->right,p,sign);
}
};