求二叉树中任意两结点的距离
来源:互联网 发布:js中onchange 编辑:程序博客网 时间:2024/04/28 19:21
与该题的一道相似题为:求二叉树中结点的最长距离。两题看似有联系,但是做法不同。
首先回顾一下:如何求二叉树中两结点的最长距离,即两点之间边数。
分析:距离和深度之间存在必然联系。如果已知最长距离的两结点的最低公共根节点r,那么我们求r的左右子树深度相加即最长距离求出。如下图所示:
我们发现A和B是最长距离,他们的最低公共根节点为C,假如我们知道C的左右子树高度均为3,并且最长路径通过C,那么最长路径必定为3+3=6.因此,问题转化成求每个结点的左右子树深度,并取每个结点左右子树深度和的最大值即可。
因此我们采用Result结构体,记录以该结点为根的子树中距离最大值和该结点的最大深度。
本质还是动态规划思想。
代码如下:
- struct BinaryTreeNode
- {
- char m_chValue;
- BinaryTreeNode* m_pLeft;
- BinaryTreeNode* m_pRight;
- };
- struct Result
- {
- int nMaxDistance;
- int nMaxDepth;
- };
- Result GetMaxDistance(BinaryTreeNode *& pRoot)
- {
- if (!pRoot)
- {
- Result empty={-1,-1};
- return empty;
- }
- Result leftResult = GetMaxDistance(pRoot->m_pLeft);
- Result rightResult = GetMaxDistance(pRoot->m_pRight);
- <span style="white-space:pre"> </span>
- Result result;
- result.nMaxDepth = 1+ max(leftResult.nMaxDepth, rightResult.nMaxDepth);
- result.nMaxDistance =max( max(leftResult.nMaxDistance, rightResult.nMaxDistance), (leftResult.nMaxDepth+rightResult.nMaxDepth+2) );
- return result;
- }
- // 输入:先序和中序的第一个指针和最后一个指针,
- // 递归调用,每次缺点当前结点
- BinaryTreeNode* ConstructCore(char* startPerorder, char* endPreorder, char* startInorder, char* endInorder)
- {
- //先序第一个为根节点
- char rootValue = startPerorder[0];
- BinaryTreeNode* root = new BinaryTreeNode;
- root->m_chValue = rootValue;
- root->m_pLeft = root->m_pRight = NULL;
- //递归退出条件
- if ( startPerorder==endPreorder )
- {
- if ( startInorder==endInorder && *startPerorder==*endInorder )
- return root;
- else
- throw std::exception("Invalid input."); //异常处理
- }
- // 在中序遍历中找到根节点的值
- char* rootInorder = startInorder;
- while(rootInorder<=endInorder && *rootInorder!=rootValue)
- ++rootInorder;
- //异常处理
- if ( rootInorder==endInorder && *rootInorder!=rootValue)
- throw std::exception("Invalid input.");
- int leftLength = rootInorder - startInorder;
- char* leftPreorderEnd = startPerorder+leftLength;
- if ( leftLength > 0 )
- {
- //构建左子树
- root->m_pLeft = ConstructCore(startPerorder+1,leftPreorderEnd,startInorder, rootInorder-1);
- }
- if ( leftLength < endPreorder-startPerorder )
- {
- //构建右子树
- root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
- }
- return root;
- }
- //根据先序和中序构建二叉树
- BinaryTreeNode* Construct(char* preorder, char* inorder, char length)
- {
- if(preorder==NULL || inorder==NULL || length <=0)
- return NULL;
- return ConstructCore(preorder, preorder+length-1, inorder,inorder+length-1);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- char* pInorder = "abcdefghi";
- char* pPreorder = "ecbadhfgi";
- BinaryTreeNode* pRoot = Construct( pPreorder,pInorder,strlen(pInorder) );
- Result result = GetMaxDistance(pRoot);
- cout << "最大距离为:" << result.nMaxDistance <<endl;
- return 0;
- }
问题定义:给定一非二叉排序树,随意给出任意两个结点值,求二者的距离
分析:求两结点的距离,实际是找二者的从根到该结点的路径,路径找到,那么距离就有了。
例如:找结点值为a和d的距离,a的路径为ecba,d的路径为ecd。那么二者的路径就为abcd,距离就是3.
问题转化成如何求该结点到根节点的路径。我们可以后序遍历二叉树,同时用栈或数组保存当前路径,如果和结点值匹配的话,保存当前路径,直到找到两结点值路径为止。
步骤如下:
1:后序遍历先序处理获得该两个结点值的路径字符串;
2:比较两个路径字符串,不相同字符即二者的距离长度;
3:如果找不全两结点值,则距离为0。
代码:
- //在以pRoot为根的树中查找结点文本值分别为node1Val和node2Val的二者距离
- int GetDistanceBetNodes(BinaryTreeNode* pRoot, char node1Val, char node2Val)
- {
- if(!pRoot) //如果是空
- return 0;
- vector<BinaryTreeNode*> path;
- BinaryTreeNode* pTempNode = pRoot;
- int i,nFindCount = 0;
- bool Tag[50]; //记录栈中结点是否左右子树遍历玩,如果遍历完,置true
- memset(Tag,0,sizeof(bool)*50);
- char *pNodePath[2] = {NULL}; //开辟一个指针数组,指向两个字符的路径
- while ( pTempNode || !path.empty() ) //当所有结点都遍历完或者已经找到二者的路径则终止
- {
- while ( pTempNode )
- {
- path.push_back(pTempNode);
- //判断入栈元素是否与要查找的结点值相等,相等则赋值
- if ( pTempNode->m_chValue==node1Val || pTempNode->m_chValue==node2Val )
- {
- pNodePath[nFindCount] = new char[path.size()+1];
- for (i=0; i<(int)path.size(); i++)
- {
- pNodePath[nFindCount][i] = path.at(i)->m_chValue;
- }
- pNodePath[nFindCount++][i] = '\0';
- if (nFindCount==2)
- break;
- }
- pTempNode = pTempNode->m_pLeft;
- }
- while ( !path.empty() && Tag[path.size()-1] == true ) //如果栈顶元素左右子树已遍历完在遍历该结点
- {
- // cout << path.back()->m_chValue <<endl;
- Tag[path.size()-1] = false; //此时Tag[path.size()-1]对应位置没有元素,将它置初始值,方便下次对该位置元素做判断
- path.pop_back();
- }
- if ( !path.empty() )
- {
- Tag[path.size()-1] = true;
- pTempNode = path.back();
- pTempNode = pTempNode->m_pRight;
- }
- }
- //如果二者不全有值,距离默认为0
- if ( !(pNodePath[0]&&pNodePath[1]) )
- return 0;
- //遍历两结点路径字符串,不相同字符个数即二者的路径长度
- char *p1 = pNodePath[0];
- char *p2 = pNodePath[1];
- int distance = 0;
- while ( *p1!='\0' || *p2!='\0' )
- {
- if ( *p1 == *p2 )
- {
- p1++;
- p2++;
- }
- else
- {
- if (*p1 != '\0')
- {
- distance++;
- p1++;
- }
- if (*p2 != '\0')
- {
- distance++;
- p2++;
- }
- }
- }
- delete pNodePath[0];
- delete pNodePath[1];
- return distance;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- char* pInorder = "abcdefghi";
- char* pPreorder = "ecbadhfgi";
- BinaryTreeNode* pRoot = Construct( pPreorder,pInorder,strlen(pInorder) );
- cout << GetDistanceBetNodes(pRoot, 'a', 'e') <<endl;
- return 0;
- }
扩展:
那么,在一棵多叉树中同时找多个结点文本值的最低公共祖先结点,方法也是一样的。即后序遍历,先序处理。
0 0
- 求二叉树中任意两结点的距离
- 求二叉树中任意两结点的距离
- 第十一题:求二叉树任意两结点的最大距离
- 求二叉树中任意两结点的最近共同祖先的算法及其证明
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求一个二叉树中两个结点的最大距离
- 二叉树中任意两节点的距离
- 求二叉树结点的最大距离
- 二叉树中两个结点的距离
- 二叉树中两个结点的距离
- 二叉树中结点的最大距离
- 求二叉树两结点最近的共同祖先结点
- hdu2874 LCA求森林中任意两节点的距离
- 求二叉树的宽度(结点的最大距离)
- 求二叉树中结点的最大距离 【微软面试100题 第十一题】
- 敏捷开发中的StoryWall(进度管理)
- hdu 4920 Matrix multiplication 多校第五场 稀疏矩阵乘法
- 9.RelativeLayout 的一些常用属性
- [火狐]已阻止读取混合活动内容 "http://10.235.59.215:8888/......."
- MongoDB 入门简介
- 求二叉树中任意两结点的距离
- 南阳理工458 小光棍数
- 快速幂取模总结
- URAL1132 Square Root 二次剩余模版题
- 英特尔 Android* 开发人员指南上的对等应用
- Average is not Fast Enough! hdoj 1036
- C#_xml文件请求及接收数据
- myeclipse中disable maven nature如何恢复
- 设计模式之外观模式