思路:
(1)判断一棵二叉树是否是完全二叉树,我们利用层序遍历的思想,设置标志位为true,先把根节点压进栈,再去看根的左孩子是不是存在,不存在将标志位设为false,再去遍历整棵树。
(2)求二叉树中两个节点的最近公共祖先。
要求考虑以下三种种情况
1:二叉树每个节点有parent(三叉链)
思路:
根据两个节点分别找到自己的所有父节点直到根,并压入两个栈中,如果栈不为空从两个栈中取节点,如果相等先保存起来(防止返回多个公共祖先),如果有多个公共节点,Pop至最后一个相等的节点再返回。
2:二叉树是搜索二叉树。
思路:
搜索树的规律是,左孩子小于根,右孩子大于根,所以我们只需要递归去判定两个节点是不是某个节点的左右即可。
3:就是普通二叉树。(尽可能实现时间复杂度为O(N))
思路:
方法一:时间复杂度为O(N*N)
思路等同搜索二叉树,先序递归的方法。先递归去找两节点在树中的位置,如果在根节点的左右,则根节点就是这两节点的公共祖先。再去递归根的左子树和右子树。因为递归次数是N每次递归的次数是N所以时间复杂度为O(N*N)
方法二:时间复杂度为O(N)
先实现一个函数找到这两个节点,再让这两个节点及其所有父节点分别压入两个栈中,再去比较两个栈中的元素,从而找到最近的公共祖先节点。递归遍历一遍时间复杂度为O(N)
实现代码及测试代码
#include <iostream>
using namespace std;
#include <stack>
#include <queue>
#include <assert.h>
namespace BINARY
{
struct Node
{
int elem;
Node* left;
Node* right;
Node* parent;
Node(int x)
:elem(x)
, left(NULL)
, right(NULL)
, parent(NULL)
{}
};
//判断一个节点是不是在一棵树
bool IsInTree(Node* root, Node* x)
{
assert(x);
if (NULL == root)
return false;
if (root->elem == x->elem)
return true;
return IsInTree(root->left, x) || IsInTree(root->right, x);
}
//判断一棵树是否是另外一棵树的子树
bool IsSon(Node* tree1, Node* tree2)
{
if (tree2 == NULL)
return true;
if (tree1 == NULL)
return false;
if (tree1->elem != tree2->elem)
return false;
return IsSon(tree1->left, tree2->left) && IsSon(tree1->right, tree2->right);
}
bool IsSonTree(Node* tree1, Node* tree2)
{
bool ret = false;
if (tree1 == NULL)
return false;
if (tree2 == NULL)
return true;
if (tree1 != NULL && tree2 != NULL)
{
if (tree1->elem == tree2->elem)
ret = IsSon(tree1, tree2);
if (!ret)
ret = IsSonTree(tree1->left, tree2);
if (!ret)
ret = IsSonTree(tree1->right, tree2);
}
return ret;
}
//判断一棵树是不是完全二叉树,层序(使用队列)遍历二叉树,如果左为空,将tag置为false
bool IsComplectTree(Node* root)
{
queue<Node*> q;
bool tag = true;
if (root)
q.push(root);
while (!q.empty())
{
Node* front = q.front();
q.pop();
if (front->left)
{
if (tag == false)
return false;
q.push(front->left);
}
else
{
tag = false;
}
if (front->right)
{
if (tag == false)
return false;
q.push(front->right);
}
else
tag = false;
}
//到这个位置队列为空,树层序遍历完了,返回空
return true;
}
//求节点的公共祖先,若二叉树是搜索树
Node* PublicAncestor1(Node* root, Node* x1, Node* x2)
{
if (NULL == root)
return NULL;
assert(x1 && x2);
if (root->elem >= x1->elem && root->elem <= x2->elem || root->elem <= x1->elem && root->elem >= x2->elem)
return root;
else if (root->elem > x1->elem && root->elem > x2->elem)
return PublicAncestor1(root->left, x1, x2);
else
return PublicAncestor1(root->right, x1, x2);
}
//求节点的公共祖先,若二叉树是三叉链
Node* PublicAncerstor2(Node* root, Node* x1, Node* x2)
{
if (NULL == root)
return NULL;
assert(x1 && x2);
stack<Node*> s1;
stack<Node*> s2;
Node* cur1 = x1;
Node* cur2 = x2;
while (cur1->parent != NULL)
{
if (cur1->parent->elem == x2->elem)
return x2;
cur1 = cur1->parent;
s1.push(cur1);
}
while (cur2->parent != NULL)
{
if (cur2->parent->elem == x1->elem)
return x1;
cur2 = cur2->parent;
s2.push(cur2);
}
Node* node = NULL;
while (!s1.empty() && !s2.empty())
{
if (s1.top()->elem == s2.top()->elem)
node = s1.top();
else
return node;
s1.pop();
s2.pop();
}
return node;
}
//求公共节点,二叉树为普通二叉树时间复杂度为O(n*n)
Node* GetNodeAncestor(Node* root, Node* x1, Node* x2)
{
if (root == NULL)
return NULL;
assert(x1 && x2);
if (x1 == root || x2 == root)
return root;
bool x1left, x1right, x2left, x2right;
x1left = IsInTree(root->left, x1);
x1right = IsInTree(root->right, x1);
assert(x1left || x1right);
x2left = IsInTree(root->left, x2);
x2right = IsInTree(root->right, x2);
assert(x2left || x2right);
if (x1left && x2right || x1right && x2left)
return root;
else if (x1left && x2left)
return GetNodeAncestor(root->left, x1, x2);
else
return GetNodeAncestor(root->right, x1, x2);
}
//求公共节点,二叉树为普通二叉树时间复杂度为O(n)
bool GetNodePaths(Node* root, stack<Node*>& s, Node* x)
{
if (NULL == root)
return false;
s.push(root);
if (x == root)
return true;
bool left = GetNodePaths(root->left, s, x);
if (left)
return true;
bool right = GetNodePaths(root->right, s, x);
if (right)
return true;
s.pop();
return false;
}
Node* GetNodeAncestorN(Node* root, Node* x1, Node* x2)
{
if (NULL == root)
return NULL;
assert(x1 && x2);
stack<Node*> s1, s2;
if (!GetNodePaths(root, s1, x1) || !GetNodePaths(root, s2, x2))
return NULL;
while(s1.size() != s2.size())
{
if(s1.size() > s2.size())
s1.pop();
if(s1.size() < s2.size())
s2.pop();
}
while (!s1.empty() && !s2.empty() && s1.top()!=s2.top())
{
s1.pop();
s2.pop();
}
return s1.top();
}
void test()
{
Node* n1 = new Node(1);
Node* n2 = new Node(2);
Node* n3 = new Node(3);
Node* n4 = new Node(4);
Node* n5 = new Node(5);
n1->left = n2;
n2->parent = n1;
n1->right = n3;
n3->parent = n1;
n3->left = n4;
n4->parent = n3;
n3->right = n5;
n5->parent = n3;
Node* m1 = new Node(2);
Node* m2 = new Node(4);
Node* m3 = new Node(5);
m1->left = m2;
m1->right = m3;
//Node* n6 = new Node(2);
//cout << IsInTree(n1, n6)<<endl;
//cout << IsSonTree(n1, m1) << endl;
//cout << IsComplectTree(m1) << endl;
Node* ret = GetNodeAncestorN(n1, n4, n5);
cout << ret->elem << endl;
cout << PublicAncerstor2(n1, n2, n5)->elem << endl;
}
}