题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if (pNode == NULL)
return NULL;
if (pNode->right != NULL)
{
TreeLinkNode *find=pNode->right;
while (find->left)
{
find = find->left;
}
return find;
}
{
while (pNode->next)
{
TreeLinkNode *find = pNode->next;
if (find->left == pNode)
return find;
pNode = pNode->next;
}
return NULL;
}
}
};
这里我们首先要知道什么是二叉树的中序遍历,我感觉既然能做剑指offer的题对中序遍历应该是都有一定的了解了
中序遍历是有很多种情况的。
这是我们的一个二叉树,他的中序遍历是1,3,2,4,6,5,7 左孩子-》根结点-》右孩子。
如果是1的话我们就要去找他的父亲结点,如果是2的话就要去找他父亲结点的父亲结点。4的话需要去找他的右孩子的最左结点。
这里简单总结一下这些情况:
-
有右孩子的。
如果当前传入的结点是有右孩子的那下一个结点一定是他右子树的最左结点,有右孩子就不会去别的地方找,肯定在右子树里边。所以
if (pNode->right != NULL)
{
TreeLinkNode *find=pNode->right;
while (find->left)
{
find = find->left;
}
return find;
}
-
右孩子为空并且不是最后一个节点的
也就是说1,2,6我们都可以看成一种情况,既然他没有右孩子,并且它的左孩子他自己都已经遍历过了那说明他们这颗子树遍历过了,那就要去找他的父亲结点,就比如我们传入1我们就要去找3,传入2就要去找4,1和2不同的就是他们一个是父亲结点的左孩子一个是父亲结点的右孩子,如果是父亲结点的左孩子,那就要返回他的父亲结点了,如果是父亲结点的右孩子说明父亲结点也遍历说了,那就要去找父亲结点的父亲结点,一直找到某个节点是他父亲结点的左孩子,那返回那个父亲结点就可以。
while (pNode->next)
{
TreeLinkNode *find = pNode->next;
if (find->left == pNode)
return find;
pNode = pNode->next;
}
-
右孩子为空并且是最后一个节点
这里就是我们的7了,他和126不同的是他再去找父亲结点也不可能说找到一个节点是他父亲结点的左孩子,一直找到根都是,这里我认为处理的很巧妙,因为跟结点的父亲结点就是NULL,我们这里正好要返回的也是空,所以他就和第二种情况一起处理了,如果我们找父亲结点找到了一个节点是他父亲结点的左孩子,那我们就返回他的父亲结点,如果找到操作的结点父亲结点是空了,说明到根了找不到符合情况的了,直接返回根节点的父亲结点,也就是空节点。
再给大家分享一个选择题:
在系统内存中设置磁盘缓冲区的主要目的是()。
A.减少磁盘 I/O 次数
B.减少平均寻道时间
C.提高磁盘数据可靠性
D.实现设备无关性
A,因为磁盘和内存的访问速度是有着很大的差距的,内存读取的速度很快但是我们的磁盘速度就慢了许多,所以设立了一个磁盘缓冲区,我们把常用的文件放在这个缓冲区里,这样的话我们读取的时候就不用经常去磁盘中读取,这样操作的速度就提升了很多。
磁盘和内存的速度差异,决定了可以将内存经常访问的文件调入磁盘缓冲区,从高速缓存中复制的访问比磁盘 I/O 的机械操作要快很多很多。(来自王道论坛)