剑指offer笔记面试题8----二叉树的下一个节点
题目:给定一棵二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?树中的节点除了有两个分别指向左、右子节点的指针,还有一个指向父节点的指针。
测试用例:
- 普通二叉树(完全二叉树,不完全二叉树)。
- 特殊二叉树(所有节点都没有右子节点的二叉树;所有节点都没有左子节点的二叉树;只有一个节点的二叉树;二叉树的根节点指针为nullptr)。
- 不同位置的节点的下一个节点(下一个节点为当前节点的右子节点、右子树的最左子节点、父节点、跨层的父节点等;当前节点没有下一个节点)。
测试代码:
void Test(char* testName, BinaryTreeNode* pNode, BinaryTreeNode* expected)
{
if(testName != nullptr)
printf("%s begins: ", testName);
BinaryTreeNode* pNext = GetNext(pNode);
if(pNext == expected)
printf("Passed.\n");
else
printf("FAILED.\n");
}
// 8
// 6 10
// 5 7 9 11
void Test1_7()
{
BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNode9 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNode11 = CreateBinaryTreeNode(11);
ConnectTreeNodes(pNode8, pNode6, pNode10);
ConnectTreeNodes(pNode6, pNode5, pNode7);
ConnectTreeNodes(pNode10, pNode9, pNode11);
Test("Test1", pNode8, pNode9);
Test("Test2", pNode6, pNode7);
Test("Test3", pNode10, pNode11);
Test("Test4", pNode5, pNode6);
Test("Test5", pNode7, pNode8);
Test("Test6", pNode9, pNode10);
Test("Test7", pNode11, nullptr);
DestroyTree(pNode8);
}
// 5
// 4
// 3
// 2
void Test8_11()
{
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
ConnectTreeNodes(pNode5, pNode4, nullptr);
ConnectTreeNodes(pNode4, pNode3, nullptr);
ConnectTreeNodes(pNode3, pNode2, nullptr);
Test("Test8", pNode5, nullptr);
Test("Test9", pNode4, pNode5);
Test("Test10", pNode3, pNode4);
Test("Test11", pNode2, pNode3);
DestroyTree(pNode5);
}
// 2
// 3
// 4
// 5
void Test12_15()
{
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
ConnectTreeNodes(pNode2, nullptr, pNode3);
ConnectTreeNodes(pNode3, nullptr, pNode4);
ConnectTreeNodes(pNode4, nullptr, pNode5);
Test("Test12", pNode5, nullptr);
Test("Test13", pNode4, pNode5);
Test("Test14", pNode3, pNode4);
Test("Test15", pNode2, pNode3);
DestroyTree(pNode2);
}
void Test16()
{
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
Test("Test16", pNode5, nullptr);
DestroyTree(pNode5);
}
本题考点:
- 考查应聘者对二叉树中序遍历的理解程度。只有对二叉树的遍历算法有了深刻的理解,应聘者才有可能准确找出每个节点的中序遍历的下一个节点。
- 考查应聘者分析复杂问题的能力。应聘者只有画出二叉树的结构图、通过具体的例子找出中序遍历下一个节点的规律,才有可能设计出可行的算法。
实现代码:
#include <cstdio>
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
BinaryTreeNode* m_pParent;
};
BinaryTreeNode* GetNext(BinaryTreeNode* pNode)
{
if(pNode == nullptr)
return nullptr;
BinaryTreeNode* pNext = nullptr;
if(pNode->m_pRight != nullptr)
{
BinaryTreeNode* pRight = pNode->m_pRight;
while(pRight->m_pLeft != nullptr)
pRight = pRight->m_pLeft;
pNext = pRight;
}
else if(pNode->m_pParent != nullptr)
{
BinaryTreeNode* pCurrent = pNode;
BinaryTreeNode* pParent = pNode->m_pParent;
while(pParent != nullptr && pCurrent == pParent->m_pRight)
{
pCurrent = pParent;
pParent = pParent->m_pParent;
}
pNext = pParent;
}
return pNext;
}
// ==================== 辅助代码用来构建二叉树 ====================
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
BinaryTreeNode* pNode = new BinaryTreeNode();
pNode->m_nValue = value;
pNode->m_pLeft = nullptr;
pNode->m_pRight = nullptr;
pNode->m_pParent = nullptr;
return pNode;
}
void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
if(pParent != nullptr)
{
pParent->m_pLeft = pLeft;
pParent->m_pRight = pRight;
if(pLeft != nullptr)
pLeft->m_pParent = pParent;
if(pRight != nullptr)
pRight->m_pParent = pParent;
}
}
void PrintTreeNode(BinaryTreeNode* pNode)
{
if(pNode != nullptr)
{
printf("value of this node is: %d\n", pNode->m_nValue);
if(pNode->m_pLeft != nullptr)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is null.\n");
if(pNode->m_pRight != nullptr)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is null.\n");
}
else
{
printf("this node is null.\n");
}
printf("\n");
}
void PrintTree(BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot);
if(pRoot != nullptr)
{
if(pRoot->m_pLeft != nullptr)
PrintTree(pRoot->m_pLeft);
if(pRoot->m_pRight != nullptr)
PrintTree(pRoot->m_pRight);
}
}
void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != nullptr)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight;
delete pRoot;
pRoot = nullptr;
DestroyTree(pLeft);
DestroyTree(pRight);
}
}
int main(int argc, char* argv[])
{
Test1_7();
Test8_11();
Test12_15();
Test16();
}
剑指offer笔记面试题8----二叉树的下一个节点的更多相关文章
- 【剑指offer】面试题 8. 二叉树的下一个结点
面试题 8. 二叉树的下一个结点 NowCoder 题目描述 给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指 ...
- 剑指Offer(书):二叉树的下一个节点
题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 分析:若一个节点有右子树,那么他的下一个节点就是他右子树中 ...
- 《剑指offer》面试题39 二叉树的深度(java)
摘要: 今天翻到了<剑指offer>面试题39,题目二中的解法二是在函数的参数列表中通过指针的方式进行传值,而java是没有指针的,所以函数要进行改造.然而我翻了下别人的java版本(我就 ...
- 剑指offer笔记面试题7----重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如,输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历序列 ...
- 【剑指offer】面试题 55. 二叉树的深度
面试题 55. 二叉树的深度 题目一:二叉树的深度 题目描述:输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. Java 实现 ...
- 【剑指offer】面试题 23. 链表中环的入口节点
面试题 23. 链表中环的入口节点
- 《剑指Offer》面试题-重建二叉树
题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7 ...
- 《剑指offer》面试题25 二叉树中和为某一值的路径 Java版
(判断是否有从根到叶子节点的路径,其和为给定值.记录这些路径.) 我的方法:这道题我是按照回溯的思路去做的,我们需要一个数据结构来保存和删除当前递归函数中添加的值.这里要打印一条路径,我们可以选择Li ...
- 《剑指offer》面试题19 二叉树的镜像 Java版
书中方法:这道题目可能拿到手没有思路,我们可以在纸上画出简单的二叉树来找到规律.最后我们发现,镜像的实质是对于二叉树的所有节点,交换其左右子节点.搞清楚获得镜像的方法,这道题实际上就变成了一道二叉树遍 ...
随机推荐
- JQuery之选择集过滤
JQuery选择集过滤应用如下: 代码实现: <script src="JS/jquery-3.4.1.js"></script> <script&g ...
- python解析ifconfig 输出成字典
有个需求需要将ifcofig输出解析出来,这里将写的整理出来.方便后续使用. eth0 Link encap:Ethernet HWaddr 00:50:53:b2:23:e6 inet addr:1 ...
- Java中的try-catch-finally异常处理
Java中的try-catch-finally异常处理 一.异常处理 异常(Exception):是在运行发生的不正常情况. 原始异常处理: if(条件) { 处理办法1 处理办法2 处理办法3 } ...
- css Backgroud-clip (文字颜色渐变)
首先来瞄一下background-clip,这个属性是干嘛的? 顾名思义,背景裁剪... 按照我自己的理解就是背景的显示区域 此处粘上MDN的示例链接(嫌麻烦的,后面我也贴上截图)https:// ...
- 使用iCamera 测试MT9F002 1400w高分辨率摄像头说明 续集2
使用iCamera 测试MT9F002 1400w高分辨率摄像头说明 续集2 本方案测试三种分辨率输出(其他更多分辨率设置,可以参考手册配置) 3776*3288=1241万像素 3776*2832= ...
- idea 上传svn忽略文件
在idea最下面找到Version Control 默认我们svn提交的文件都在Default ChangeList中 我们创建一个新的ChangeList
- 【Java8流】使用学习
[Java8流]使用学习 ============================================= 1.删除子目录及文件 ============================== ...
- Rar5.20 key
key如下,使用方法自行百度,^_^ RAR registration dataState Grid Corporation Of China50000 PC usage licenseUID=582 ...
- AQS系列(三)- ReentrantReadWriteLock读写锁的加锁
前言 前两篇我们讲述了ReentrantLock的加锁释放锁过程,相对而言比较简单,本篇进入深水区,看看ReentrantReadWriteLock-读写锁的加锁过程是如何实现的,继续拜读老Lea凌厉 ...
- 分享一篇关于C#大文件上传的整个过程
简单写个小例子,记录一下此次大文件上传遇到的所有问题. 一.客户端(使用winform窗体实现) 具体功能: 点击“选择”按钮,选择要上传的文件 点击“上传文件”按钮,上传该文件调用UpLoad_Re ...