2013.10.8 上午八点半
问题:二叉树两结点的最低共同父结点
问题描述:
二叉树的结点定义如下:
struct TreeNode
{
int m_nvalue;
TreeNode* m_pLeft;
TreeNode* m_pRight;
};
输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。
分析一:二叉树是二叉排序树,那么位于左子树的节点都比父节点小,而位于右子树的节点都比父节点大,我们只需要从树的根节点开始和两个输入的节点进行比较。如果当前节点的值比两个节点的值都大,那么最低的共同父节点一定在当前节点的左子树中,于是下一步遍历当前节点的左子结点。如果当前节点的值比两个节点的值都小,那么最低共同父节点一定在当前节点的右子树中,于是下一步遍历当前节点的右子结点。这样在树中从上到下找到的第一个在两个输入节点的值之间的节点,就是最低的公共祖先。
代码:
#ifndef _LOWESTCOMMONPARENT_H_
#define _LOWESTCOMMONPARENT_H_
#include <iostream>
#include <vector>
#include <list>
#include <stdio.h>
using namespace std;
struct BinaryTreeNode
{
intm_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
//createnode
BinaryTreeNode*CreateBinaryTreeNode(int value)
{
BinaryTreeNode* pNode=new BinaryTreeNode();
pNode->m_nValue=value;
pNode->m_pLeft=pNode->m_pRight=NULL;
returnpNode;
}
//addleft child to parent
bool BinaryTreeAddLeftNode(BinaryTreeNode*pParent,BinaryTreeNode* pLeft)
{
if(pParent==NULL || pLeft==NULL)
{
return false;
}
if(pParent->m_pLeft!=NULL)
{
cout<<pParent->m_nValue<<" has left child"<<endl;
return false;
}
else
{
pParent->m_pLeft=pLeft;
return true;
}
}
//addright child to parent
bool BinaryTreeAddRightNode(BinaryTreeNode*pParent,BinaryTreeNode* pRight)
{
if(pParent==NULL || pRight==NULL)
{
return false;
}
if(pParent->m_pRight!=NULL)
{
cout<<pParent->m_nValue<<" has right node"<<endl;
return false;
}
else
{
pParent->m_pRight=pRight;
return true;
}
}
//二叉排序树情况
BinaryTreeNode* TheFirstCommonNode(BinaryTreeNode*pRoot,BinaryTreeNode* pNode1,BinaryTreeNode* pNode2)
{
if(pRoot==NULL|| pNode1==NULL || pNode2==NULL)
{
returnNULL;
}
if(pRoot->m_nValue>pNode1->m_nValue&& pRoot->m_nValue<pNode2->m_nValue)
{
returnpRoot;
}
if(pRoot->m_nValue<pNode1->m_nValue&& pRoot->m_nValue<pNode2->m_nValue)
{
if(pRoot->m_pRight!=NULL)
{
return(TheFirstCommonNode1(pRoot->m_pRight,pNode1,pNode2));
}
}
if(pRoot->m_nValue>pNode1->m_nValue&& pRoot->m_nValue>pNode2->m_nValue)
{
if(pRoot->m_pLeft!=NULL)
{
return(TheFirstCommonNode1(pRoot->m_pLeft,pNode1,pNode2));
}
}
}
int run()
{
//构建树
BinaryTreeNode* pRoot =CreateBinaryTreeNode(8);
BinaryTreeNode* pNode5 =CreateBinaryTreeNode(5);
BinaryTreeNode* pNode10 =CreateBinaryTreeNode(10);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode6 =CreateBinaryTreeNode(6);
BinaryTreeNode* pNode9 =CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
BinaryTreeAddLeftNode(pRoot,pNode5);
BinaryTreeAddRightNode(pRoot,pNode10);
BinaryTreeAddLeftNode(pNode5,pNode4);
BinaryTreeAddRightNode(pNode5,pNode6);
BinaryTreeAddLeftNode(pNode10,pNode9);
BinaryTreeAddRightNode(pNode10,pNode11);
//测试程序
BinaryTreeNode* pNode =TheFirstCommonNode(pRoot,pNode5,pNode11);
if(NULL != pNode)
cout<<pNode->m_nValue<<endl;
system("pause");
return 0;
}
#endif
分析二:第二个变种是树不一定是二叉树,每个结点都有一个指针指向它的父结点。于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点。
代码:
#ifndef _LOWESTCOMMONPARENT_H_
#define _LOWESTCOMMONPARENT_H_
#include <iostream>
#include <vector>
#include <list>
#include <stdio.h>
using namespace std;
struct BinaryTreeNode
{
intm_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
//createnode
BinaryTreeNode*CreateBinaryTreeNode(int value)
{
BinaryTreeNode* pNode=new BinaryTreeNode();
pNode->m_nValue=value;
pNode->m_pLeft=pNode->m_pRight=NULL;
returnpNode;
}
//addleft child to parent
bool BinaryTreeAddLeftNode(BinaryTreeNode*pParent,BinaryTreeNode* pLeft)
{
if(pParent==NULL || pLeft==NULL)
{
return false;
}
if(pParent->m_pLeft!=NULL)
{
cout<<pParent->m_nValue<<" has left child"<<endl;
return false;
}
else
{
pParent->m_pLeft=pLeft;
return true;
}
}
//addright child to parent
bool BinaryTreeAddRightNode(BinaryTreeNode*pParent,BinaryTreeNode* pRight)
{
if(pParent==NULL || pRight==NULL)
{
return false;
}
if(pParent->m_pRight!=NULL)
{
cout<<pParent->m_nValue<<" has right node"<<endl;
return false;
}
else
{
pParent->m_pRight=pRight;
return true;
}
}
//二t叉?排?序¨°树º¡Â情¨¦况?
BinaryTreeNode*TheFirstCommonNode1(BinaryTreeNode* pRoot,BinaryTreeNode*pNode1,BinaryTreeNode* pNode2)
{
if(pRoot==NULL|| pNode1==NULL || pNode2==NULL)
{
returnNULL;
}
if(pRoot->m_nValue>pNode1->m_nValue&& pRoot->m_nValue<pNode2->m_nValue)
{
returnpRoot;
}
if(pRoot->m_nValue<pNode1->m_nValue&& pRoot->m_nValue<pNode2->m_nValue)
{
if(pRoot->m_pRight!=NULL)
{
return(TheFirstCommonNode1(pRoot->m_pRight,pNode1,pNode2));
}
}
if(pRoot->m_nValue>pNode1->m_nValue&& pRoot->m_nValue>pNode2->m_nValue)
{
if(pRoot->m_pLeft!=NULL)
{
return(TheFirstCommonNode1(pRoot->m_pLeft,pNode1,pNode2));
}
}
}
//获得从pRoot到pNode的路径,存于path中 path保存了从pRoot到pNode的完整路径
bool GetNodePath(BinaryTreeNode*pRoot,BinaryTreeNode* pNode,list<BinaryTreeNode*>& path)
{
if(pRoot==pNode)
{
path.push_back(pRoot);
return true;
}
path.push_back(pRoot);
bool found=false;
if(pRoot->m_pLeft!=NULL)
{
found=GetNodePath(pRoot->m_pLeft,pNode,path);
}
if (!found&& pRoot->m_pRight!=NULL)
{
found=GetNodePath(pRoot->m_pRight,pNode,path);
}
if (!found)
{
path.pop_back();
}
returnfound;
}
//普通情况找寻节点到根节点的路径
BinaryTreeNode*TheFirstCommonNode(BinaryTreeNode* pRoot,BinaryTreeNode* pNode1,BinaryTreeNode*pNode2)
{
if(pRoot==NULL || pNode1==NULL || pNode2==NULL)
{
returnNULL;
}
BinaryTreeNode* pLastCommonNode;
list<BinaryTreeNode*> path1;
list<BinaryTreeNode*> path2;
boolgetPath1=GetNodePath(pRoot,pNode1,path1);
boolgetPath2=GetNodePath(pRoot,pNode2,path2);
if(getPath1==false || getPath2==false)
{
return false;
}
list<BinaryTreeNode*>::const_iteratoriterator1=path1.begin();
list<BinaryTreeNode*>::const_iteratoriterator2=path2.begin();
while(iterator1!=path1.end()&& iterator2!=path2.end())
{
if(*iterator1==*iterator2)
{
pLastCommonNode=*iterator1;
iterator1++;
iterator2++;
}else
{
returnpLastCommonNode;
}
}
}
int run()
{
//构建树
BinaryTreeNode* pRoot =CreateBinaryTreeNode(8);
BinaryTreeNode* pNode5 =CreateBinaryTreeNode(5);
BinaryTreeNode* pNode10 =CreateBinaryTreeNode(10);
BinaryTreeNode* pNode4 =CreateBinaryTreeNode(4);
BinaryTreeNode* pNode6 =CreateBinaryTreeNode(6);
BinaryTreeNode* pNode9 =CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 =CreateBinaryTreeNode(11);
BinaryTreeAddLeftNode(pRoot,pNode5);
BinaryTreeAddRightNode(pRoot,pNode10);
BinaryTreeAddLeftNode(pNode5,pNode4);
BinaryTreeAddRightNode(pNode5,pNode6);
BinaryTreeAddLeftNode(pNode10,pNode9);
BinaryTreeAddRightNode(pNode10,pNode11);
//测试程序
BinaryTreeNode* pNode =TheFirstCommonNode(pRoot,pNode6,pNode11);
if(NULL !=pNode)
cout<<pNode->m_nValue<<endl;
system("pause");
return 0;
}
#endif
如果没有指向父节点的指针的话,我们的主要问题就是怎么能得到从根节点分别到这两个节点的两条链表?
问题关键点:分析如果是二叉排序树的本身特性进行求解,若是普通情况则进行求路径找公共父节点
参考至:http://blog.youkuaiyun.com/attitudeisaltitude/article/details/9847245