网易面试题之求出树的直径
来源:互联网 发布:注册网络教育公司 编辑:程序博客网 时间:2024/05/18 01:21
给定一颗二叉树,求出树中的任意两个节点之间的最大距离,即树的直径。
从这个题目可以看到,树中任意两个节点的最大距离,显然应该是不同叶子间的最大距离。我们可以根据树的节点分布情况分情况考虑如何求树的直径。
情况1:对于一般的树,根结点的左子树与右子树平衡,如图1。左子树与右子树的叶子节点的最大距离,应该为左子树的深度加上右子树的深度,然后加1,即为树的直径。
情况2:根据上面的分析,我们可以明显感觉到,如果该树为一颗倾斜树,即节点的左子树与右子树不对称,那么根结点的左子树与右子树的高度相差较大,同时衍生道以根结点的左(或右)子树作为根结点的左子树和右子树高非对称,那么根据情况1来求树的直径是完全错误的。
根据上面的分析,我们需要求出以树的根结点为根结点的左右子树的高度之和diameterOfRoot之后,与以树的根结点的左(右)孩子为根结点的左右子树的高度之和diameterOflChild(diameterOfrChild)进行比较,如果diameterOfRoot最大,那么diameterOfRoot,即为所求,否则diameterOflChild或者diameterOfrChild即为所求。当前这只是一次比较的节点。这个值还需要与树的根结点的左孩子的后代,以及右孩子的后代的不同叶子间的最大距离之和进行比较。
因此,对树求出直径就是一个不断递归,不断比较的过程。
它的伪代码为:
1.输入为根结点,输出为树的直径大小,初始化树的直径大小为0,以及pNode=root。
2.如果结点pNode为null,返回;否则,根据pNode递归求出左右子树的高度,以及递归2步骤,但是其输入为pNode->lChild、pNode->rChild。比较三者pNode递归求出左右子树的高度、pNode->lChild和pNode->rChild各自返回的左孩子和右孩子为根结点的树的直径。最终,三者的最大值即为树的直径。
c++代码为:
int DiameterPathOfTree(Node *root,int& length){ if(root==NULL){ return -1; } root->MaxLeft=1+DiameterPathOfTree(root->lChild, length);//求出左孩子的高度,以及以左孩子为根结点的2叉树直径保存在length中 root->MaxRight=1+DiameterPathOfTree(root->rChild, length);//求出右孩子的高度,以右孩子为根结点的2叉树的直径保存在length中 if(root->MaxLeft+root->MaxRight>length) length=root->MaxLeft+root->MaxRight+1;//孩子的为根结点的2叉树的直径与(左子树+右子树+1)进行对比,更新直径 return (root->MaxLeft>root->MaxRight)?root->MaxLeft:root->MaxRight;//返回树的高度};
求出了树的直径大小,那么如果确定树的直径上面的节点呢?
要打印路径采用前序遍历来找到路径的根节点,根节点必须是满足:root->MaxLeft+root->MaxRight==length-1;
然后从跟节点遍历深度为root->MaxLeft-1的左子树路径和root->MaxRight-1的右子树路径。
//采用递归的方式来打印直径上的结点void PrintDepthPathOfTree(Node* root,int depth){ if(depth==-1) return; cout<<root->data<<"\t"; if(root->MaxLeft==depth) PrintDepthPathOfTree(root->lChild,depth-1); else if(root->MaxRight==depth) PrintDepthPathOfTree(root->rChild, depth-1); else return;};
//采用循环的方式来打印直径上的结点void PrintDiameterPathOfTree(Node *root,int length){ Node* pNode=root; stack<Node*> s; while (pNode!=NULL||s.size()!=0) { while (pNode!=NULL) { if(pNode->MaxLeft+pNode->MaxRight==length-1){ cout<<pNode->data<<"\t"; PrintDepthPathOfTree(pNode->lChild,pNode->MaxLeft-1); PrintDepthPathOfTree(pNode->rChild,pNode->MaxRight-1); return; } s.push(pNode); pNode=pNode->lChild; } if(s.size()!=0){ //cout<<"s.szie()==="<<s.size()<<endl; pNode=s.top(); s.pop(); pNode=pNode->rChild; } }};最后,测试程序代码有:
typedef struct Node{ int data; Node* rChild; Node* lChild; int MaxLeft; int MaxRight; Node(){ rChild=NULL; lChild=NULL; MaxLeft=-1; MaxRight=-1; }} *BinTree;int array[31]={1,2,4,8,0,0,9,0,0,5,10,11,0,0,0,0,3,6,12,0,0,13,0,0,7,14,0,0,15,0,0};void CreateBinTree(BinTree* T){ // 构造二叉链表。 T 是指向根指针的指针,故修改 *T 就修改了实参 ( 根指针 ) 本身 int ch; static int i=0; ch=array[i++]; if(ch==0) T=NULL ;// 读人空格,将相应指针置空 else{ // 读人非空格 *T=(BinTree)malloc(sizeof(Node)); // 生成结点 (*T)->data=ch ; CreateBinTree(&(*T)->lChild) ; // 构造左子树 CreateBinTree(&(*T)->rChild) ; // 构造右子树 }} int main (int argc, const char * argv[]){ // insert code here... BinTree root; CreateBinTree(&root); int length=0; cout<<"the Tree's Depth is:"<<DiameterPathOfTree(root, length)<<endl; cout<<"the Tree's Diameter is:"<<length<<endl; PrintDiameterPathOfTree(root,length); return 0;}输出结果为:
the Tree's Depth is:4
the Tree's Diameter is:8
the Nodes of Diameter are:12 5 10 11 36 12
- 网易面试题之求出树的直径
- 网易的一道面试题
- 网易的一道面试题
- 网易面试题之暗黑字符串
- (面试题)求出两两之差绝对值最小的值
- 网上看到一个的网易面试题
- 网易有道的一道算法面试题
- 一道网易面试题的解法
- [网易面试题]自己的总结
- 网易面试题引发的思考
- 网易面试题
- 网易有道面试题
- 网易游戏面试题
- 网易电面试题
- 网易面试题
- 网易招聘面试题
- 一道网易面试题
- 网易开发面试题
- char*与char[]的区别
- Android中以JAR形式封装控件 或者类库
- 基于Xcode4开发第一个iPhone程序:“Hello World”
- Android 的 生命周期_ 界面的切换 和 吐司
- 数据结构之二叉排序树
- 网易面试题之求出树的直径
- GO语言的并发
- iPhone应用程序:“Say Hello”
- 虚拟机安装10.7.3另一方法
- 图片中识别出图元(2)
- 【最长降序子序列+双向】九度OJ 题目1131:合唱队形
- UIActionSheet用法
- subversion与svn安装配置全过程
- 路由器和交换机的区别