求二叉树中任意两结点的距离
来源:互联网 发布:淘宝孔雀舞服装 编辑:程序博客网 时间:2024/04/27 23:52
与该题的一道相似题为:求二叉树中结点的最长距离。两题看似有联系,但是做法不同。
首先回顾一下:如何求二叉树中两结点的最长距离,即两点之间边数。
分析:距离和深度之间存在必然联系。如果已知最长距离的两结点的最低公共根节点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);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;}建树代码参考:http://blog.csdn.net/zhaojinjia/article/details/9305251
// 输入:先序和中序的第一个指针和最后一个指针, // 递归调用,每次缺点当前结点 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];//记录栈中结点是否左右子树遍历玩,如果遍历完,置truememset(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;}}//如果二者不全有值,距离默认为0if ( !(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;}
扩展:
那么,在一棵多叉树中同时找多个结点文本值的最低公共祖先结点,方法也是一样的。即后序遍历,先序处理。
- 求二叉树中任意两结点的距离
- 求二叉树中任意两结点的距离
- 第十一题:求二叉树任意两结点的最大距离
- 求二叉树中任意两结点的最近共同祖先的算法及其证明
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求二叉树中结点的最大距离
- 求一个二叉树中两个结点的最大距离
- 二叉树中任意两节点的距离
- 求二叉树结点的最大距离
- 二叉树中两个结点的距离
- 二叉树中两个结点的距离
- 二叉树中结点的最大距离
- 求二叉树两结点最近的共同祖先结点
- hdu2874 LCA求森林中任意两节点的距离
- 求二叉树的宽度(结点的最大距离)
- 求二叉树中结点的最大距离 【微软面试100题 第十一题】
- ubuntu qemu/kvm试玩helloos
- layout获取中间面板标题
- 内存管理GetMemory
- C#获取CPU占用率、内存占用、磁盘占用、进程信息
- android dump 分区
- 求二叉树中任意两结点的距离
- c++中SetEvent和ResetEvent的使用
- T- SQL性能优化详解
- Java枚举7常见种用法
- 编写一个Linux虚拟网卡来实现类NVI
- 不知道什么原因出现异常
- C程序设计语言--指针与数组(一)
- 【热门主题:火影忍者漩涡鸣人主题】
- git 教程