案例二 树中两个结点的最低公共祖先

2024-06-21 23:48

本文主要是介绍案例二 树中两个结点的最低公共祖先,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      问题: 树中两个结点的最低公共祖先.

    (1)是一颗二叉树,并且是二叉搜素树(根据二叉搜素树的性质求解

    (2)普通树中结点有指向父结点的指针(演变为两个链表求解第一个公共结点)


    (3)一棵普通的树,树中的结点没有指向父结点的指针(最复杂的情况)


通用的解法如下:

//记录结点的路径
bool GetNodePath(TreeNode* pRoot, TreeNode* pNode, list<TreeNode*>& path)
{if(pRoot == pNode)return true;path.push_back(pRoot);bool found = false;vector<TreeNode*>::iterator i = pRoot->m_vChildren.begin();while(!found && i < pRoot->m_vChildren.end()){found = GetNodePath(*i, pNode, path);++i;}if(!found)path.pop_back();return found;
}TreeNode* GetLastCommonNode( const list<TreeNode*>& path1,  const list<TreeNode*>& path2)
{list<TreeNode*>::const_iterator iterator1 = path1.begin();list<TreeNode*>::const_iterator iterator2 = path2.begin();TreeNode* pLast = NULL;while(iterator1 != path1.end() && iterator2 != path2.end()){if(*iterator1 == *iterator2)pLast = *iterator1;iterator1++;iterator2++;}return pLast;
}
//获取最低的公共父结点
TreeNode* GetLastCommonParent(TreeNode* pRoot, TreeNode* pNode1, TreeNode* pNode2)
{if(pRoot == NULL || pNode1 == NULL || pNode2 == NULL)return NULL;list<TreeNode*> path1;GetNodePath(pRoot, pNode1, path1);list<TreeNode*> path2;GetNodePath(pRoot, pNode2, path2);return GetLastCommonNode(path1, path2);
}// ====================测试代码====================void Test(char* testName, TreeNode* pRoot, TreeNode* pNode1, TreeNode* pNode2, TreeNode* pExpected)
{if(testName != NULL)printf("%s begins: \n", testName);TreeNode* pResult = GetLastCommonParent(pRoot, pNode1, pNode2);if((pExpected == NULL && pResult == NULL) || (pExpected != NULL && pResult != NULL && pResult->m_nValue == pExpected->m_nValue))printf("Passed.\n");elseprintf("Failed.\n");
}// 形状普通的树
//              1
//            /   \
//           2     3
//       /       \
//      4         5
//     / \      / |  \
//    6   7    8  9  10
void Test1()
{TreeNode* pNode1 = CreateTreeNode(1);TreeNode* pNode2 = CreateTreeNode(2);TreeNode* pNode3 = CreateTreeNode(3);TreeNode* pNode4 = CreateTreeNode(4);TreeNode* pNode5 = CreateTreeNode(5);TreeNode* pNode6 = CreateTreeNode(6);TreeNode* pNode7 = CreateTreeNode(7);TreeNode* pNode8 = CreateTreeNode(8);TreeNode* pNode9 = CreateTreeNode(9);TreeNode* pNode10 = CreateTreeNode(10);ConnectTreeNodes(pNode1, pNode2);ConnectTreeNodes(pNode1, pNode3);ConnectTreeNodes(pNode2, pNode4);ConnectTreeNodes(pNode2, pNode5);ConnectTreeNodes(pNode4, pNode6);ConnectTreeNodes(pNode4, pNode7);ConnectTreeNodes(pNode5, pNode8);ConnectTreeNodes(pNode5, pNode9);ConnectTreeNodes(pNode5, pNode10);Test("Test1", pNode1, pNode6, pNode8, pNode2);
}// 树退化成一个链表
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test2()
{TreeNode* pNode1 = CreateTreeNode(1);TreeNode* pNode2 = CreateTreeNode(2);TreeNode* pNode3 = CreateTreeNode(3);TreeNode* pNode4 = CreateTreeNode(4);TreeNode* pNode5 = CreateTreeNode(5);ConnectTreeNodes(pNode1, pNode2);ConnectTreeNodes(pNode2, pNode3);ConnectTreeNodes(pNode3, pNode4);ConnectTreeNodes(pNode4, pNode5);Test("Test2", pNode1, pNode5, pNode4, pNode3);
}// 树退化成一个链表,一个结点不在树中
//               1
//              /
//             2
//            /
//           3
//          /
//         4
//        /
//       5
void Test3()
{TreeNode* pNode1 = CreateTreeNode(1);TreeNode* pNode2 = CreateTreeNode(2);TreeNode* pNode3 = CreateTreeNode(3);TreeNode* pNode4 = CreateTreeNode(4);TreeNode* pNode5 = CreateTreeNode(5);ConnectTreeNodes(pNode1, pNode2);ConnectTreeNodes(pNode2, pNode3);ConnectTreeNodes(pNode3, pNode4);ConnectTreeNodes(pNode4, pNode5);TreeNode* pNode6 = CreateTreeNode(6);Test("Test3", pNode1, pNode5, pNode6, NULL);
}// 输入NULL
void Test4()
{Test("Test4", NULL, NULL, NULL, NULL);
}int _tmain(int argc, _TCHAR* argv[])
{Test1();Test2();Test3();Test4();return 0;
}




这篇关于案例二 树中两个结点的最低公共祖先的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082691

相关文章

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固 通俗易懂版)

《MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固通俗易懂版)》本文主要讲解了MySQL中的多表查询,包括子查询、笛卡尔积、自连接、多表查询的实现方法以及多列子查询等,通过实际例子和操... 目录复合查询1. 回顾查询基本操作group by 分组having1. 显示部门号为10的部门名,员

SpringBoot自定义注解如何解决公共字段填充问题

《SpringBoot自定义注解如何解决公共字段填充问题》本文介绍了在系统开发中,如何使用AOP切面编程实现公共字段自动填充的功能,从而简化代码,通过自定义注解和切面类,可以统一处理创建时间和修改时间... 目录1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3

java两个List的交集,并集方式

《java两个List的交集,并集方式》文章主要介绍了Java中两个List的交集和并集的处理方法,推荐使用Apache的CollectionUtils工具类,因为它简单且不会改变原有集合,同时,文章... 目录Java两个List的交集,并集方法一方法二方法三总结java两个List的交集,并集方法一

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插