publicBinTreeNodeSearchCommonFather(BinTreeNodenode1,BinTreeNodenode2,BinTreeNodehead)
{
returnSearchCommonFather(node1,node2,head.LeftChildTree);
}
else
returnhead;
}
难点在于对于普通二叉树的查找最近公共祖先。
非常麻烦,一般也不会问到。
感兴趣的可以去搜索“二叉树RMQ”问题。
而对于二叉排序树找公共祖先是属于LCA问题。
1-1-2-4二叉排序树转换为循环双向链表
思路仍然为递归,先将左子树变为LinkedList(LL),再将右子树变为LL,之后将左子树,Root,右子树变为一个整体的LL.
代码可以如下
#regionBST-To-DoubleSortedLinkedList
//此函数用于将两个LinkedList首尾对接。
publicBinTreeNodeAppendLL(BinTreeNodenode1,BinTreeNodenode2)
{
if(node1==null)
returnnode2;
if(node2==null)
returnnode1;
//找到尾巴节点
BinTreeNodetail1=node1.LeftChildTree;
BinTreeNodetail2=node2.RightChildTree;
//完成首尾对接,两个首尾都需要对接
tail1.RightChildTree=node2;
node2.LeftChildTree=tail1;
tail2.RightChildTree=node1;
node1.LeftChildTree=tail2;
returnnode1;
}
publicBinTreeNodeConvertBstToLinkedList(BinTreeNodehead)
{
if(head==null)returnnull;
//求出左右子树的链表。
BinTreeNodeleftLL=ConvertBstToLinkedList(head.LeftChildTree);
BinTreeNoderightLL=ConvertBstToLinkedList(head.RightChildTree);
//首先让head独立,不然乱了,具体原因可以查看Append函数。
head.RightChildTree=head;
head.LeftChildTree=head;
//嫁接
leftLL=AppendLL(leftLL,head);
leftLL=AppendLL(leftLL,rightLL);
returnleftLL;
}
#endregion
1-1-2-5计算一个二叉树的叶子数目
同样的思想,总之二叉树递归就对了,注意设置递归的出口。
代码如下
publicvoidCountTreeLeaf(BinTreeNodehead,refintcount)
{
//用Out传址方式返回数目。
count=0;
if(head!
=null)
{
if(head.LeftChildTree==null&&head.RightChildTree==null)
count++;
//分别计算左右子树,计算完毕后Count即为叶子数目。
CountTreeLeaf(head.LeftChildTree,refcount);
CountTreeLeaf(head.RightChildTree,refcount);
}
}
//没有带返回值,也没有调试,这样不方便是需要在调用时确定Count为0,或者可以用返回int值的。
左右相加即可
1-1-2-6求二叉树叶子节点的最大距离
此为编程之美上的一道算法题,文章在最后着重说了如何控制递归的调用和退出。
所谓距离,就是指两个节点之间的距离。
可以想象,距离最远两个节点必然为两个叶子节点,假设根节点为K,两个最大距离的节点为U和V,那么有两种情况:
(1)U和V分别在K节点的两个子树上,那么他们之间的路线必然经过K.
(2)U和V在K节点的一个子树上,那么他们之间的路线必然不经过K.
问题即可以转化为在子树上求最大距离的点,之后Max一下就可以了。
注:
在做这个问题的时候,需要在以前的BinTreeNode重新派生一个类,其中多出来两个属性用以记录该节点左子树和右子树中的最长距离,或者直接加也可,否则无法编译通过。
代码如下,参照编程之美。
intmaxlen=0;
publicvoidFindMaxLen(BinTreeNodehead)
{
//空树
if(head==null)return;
//一下两步用于判断左右子树是否为空,在给属性赋值完毕之后,用递归确保程序执行,而真正算距离的还没开始,也是到达叶子节点以后的反弹阶段。
if(head.LeftChildTree==null)
{
head.nMaxLeft=0;
}
else
{
FindMaxLen(head.LeftChildTree);
}
if(head.RightChildTree==null)
{
head.nMaxRight=0;
}
else
{
FindMaxLen(head.RightChildTree);
}
//这里计算左子树的最大距离,非叶子节点都要经过这里两个逻辑中至少一个。
if(head.LeftChildTree!
=null)
{
intnTempMax=0;
//判断左右子树哪个更深
head.LeftChildTree.nMaxLeft>head.LeftChildTree.nMaxRight?
nTempMax=head.LeftChildTree.nMaxLeft:
nTempMax=head.LeftChildTree.nMaxRight;
//将左右子树更深的+和根节点的这条连线,作为这个子树的深度。
head.LeftChildTree.nMaxLeft=nTempMax+1;
}
//右子树
if(head.RightChildTree!
=null)
{
intnTempMax=0;
//判断左右子树哪个更深
head.RightChildTree.nMaxLeft>head.RightChild