剑指offer 二叉树的下一个结点(C++)

该博客主要介绍了如何在C++中解决二叉树问题,寻找给定节点在中序遍历顺序下的下一个节点。作者通过定义查找根节点和中序遍历的函数,利用vector存储遍历序列,找到目标节点并返回其后继节点。文章强调了在C++中使用泛型编程的重要性,并提到了在Visual Studio 2013上的实现,表示还有不依赖vector的解决方案待探索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

解题思路

  • 定义一个寻找根结点的函数,找到根结点,如果pNode本身为根结点,直接返回。
  • 定义一个中序遍历函数,并用vector容器存储二叉树中序遍历序列。
  • 找到容器中和pNode匹配的结点,返回结点的下一个结点即可。结点为空返回空,pNode在vector中的最后一个位置返回空。

代码实现

/*
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* FindpRoot(TreeLinkNode* pNode) // 寻找pNode所在二叉树的根结点
    {
        if(pNode == NULL) // 结点为空  返回NULL
            return NULL;
        if(pNode->next == NULL) // pNode为根结点直接返回该结点
            return pNode;
        TreeLinkNode* pRoot = pNode->next;
        for( ;pRoot->next; pRoot = pRoot->next);
        return pRoot;
    }
    
    void InOrderBiTree(TreeLinkNode* pRoot, vector<TreeLinkNode*> &vpNode) // 中序遍历二叉树
    {
        if(pRoot)
        {
            if(pRoot->left)
                InOrderBiTree(pRoot->left, vpNode);
            vpNode.push_back(pRoot);
            if(pRoot->right)
                InOrderBiTree(pRoot->right, vpNode);
        }
    }
    
    TreeLinkNode* FindNextNode(TreeLinkNode* pNode, vector<TreeLinkNode*> &vpNode)
    {
        if(pNode == NULL) // 结点为空返回空
            return NULL;
        if(vpNode.empty()) // 容器为空 返回空
            return NULL;
        vector<TreeLinkNode*>::iterator iter = vpNode.begin();
        for(; iter != vpNode.end(); iter++)
        {
            if(*iter == pNode)
                break;
        }
        if((++iter) == vpNode.end()) // pNode为最后一个结点 返回空
            return NULL;
        return *iter; // 返回pNode的下一个结点指针
    }
    
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(pNode == NULL)
            return NULL;
        TreeLinkNode* pRoot = FindpRoot(pNode);
        vector<TreeLinkNode*> vpNode;
        InOrderBiTree(pRoot, vpNode);
        
        return FindNextNode(pNode, vpNode);
    }
};

毕竟是C++,还是多用一些泛型算法比较好,比如上述代码部分的:

for(; iter != vpNode.end(); iter++)
{
    if(*iter == pNode)
        break;
}

可以改成如下形式:

iter = find(vpNode.begin(), vpNode.end(), pNode);

尽量多的使用泛型编程,要逐渐适应C到C++的转变。

主函数部分

又在VS2013上实现了一遍

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<vector>
using namespace std;

struct TreeLinkNode {
	int val;
	struct TreeLinkNode *left;
	struct TreeLinkNode *right;
	struct TreeLinkNode *next;
	TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {

	}
};

TreeLinkNode* CreateTree() // 创建这种二叉树
{
	TreeLinkNode* root = new TreeLinkNode(5); // 注意new的用法 初始化后必须赋值
	root->next = NULL;
	TreeLinkNode* left1 = new TreeLinkNode(3);
	left1->next = root;
	TreeLinkNode* right1 = new TreeLinkNode(7);
	right1->next = root;
	root->left = left1; // 赋值问题 老是出错
	root->right = right1;
	TreeLinkNode* left2 = new TreeLinkNode(2);
	TreeLinkNode* right2 = new TreeLinkNode(4);
	left1->left = left2;
	left2->next = left1;
	left1->right = right2;
	right2->next = left1;
	TreeLinkNode* left3 = new TreeLinkNode(6);
	TreeLinkNode* right3 = new TreeLinkNode(8);
	right1->left = left3;
	left3->next = right1;
	right1->right = right3;
	right3->next = right1;
	return root;
}

void printBiTree(vector<TreeLinkNode*> &vpNode) // 打印数组
{
	if (vpNode.empty())
	{
		return;
	}
	vector<TreeLinkNode*>::iterator iter = vpNode.begin();
	for (; iter != vpNode.end(); iter++)
	{
		cout << (*iter)->val << " ";
	}
	cout << endl;
}

TreeLinkNode* FindpRoot(TreeLinkNode* pNode) // 返回该结点所在树的根结点
{
	if (pNode == NULL)
		return NULL;
	if (pNode->next == NULL)
	{
		return pNode;
	}
	TreeLinkNode* pRoot = pNode->next;
	for (; pRoot->next; pRoot = pRoot->next);
	return pRoot;
}

void InOrderBiTree(TreeLinkNode* pRoot, vector<TreeLinkNode*> &vpNode) // 中序遍历二叉树 结果存在vector容器中
{
	if (pRoot)
	{
		if (pRoot->left)
			InOrderBiTree(pRoot->left, vpNode);
		vpNode.push_back(pRoot);
		if (pRoot->right)
			InOrderBiTree(pRoot->right, vpNode);
	}
}

TreeLinkNode* FindNextNode(TreeLinkNode* pNode, vector<TreeLinkNode*> &vpNode)
{
	if (pNode == NULL)
		return NULL;
	if (vpNode.empty())
		return NULL;
	vector<TreeLinkNode*>::iterator iter = vpNode.begin();
	for (; iter != vpNode.end(); iter++)
	{
		if (*iter == pNode)
			break;
	}
	if ((++iter) == vpNode.end())
		return NULL;
	return *iter;
}

TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
	if (pNode == NULL)
		return NULL;
	TreeLinkNode* pRoot = FindpRoot(pNode);
	vector<TreeLinkNode*> vpNode;
	InOrderBiTree(pRoot, vpNode);

	return FindNextNode(pNode, vpNode);
}

void main()
{
	TreeLinkNode* pRoot = CreateTree();
	vector<TreeLinkNode*> v;
	InOrderBiTree(pRoot, v);
	printBiTree(v); // 2 3 4 5 6 7 8
	TreeLinkNode* pNode = pRoot->right->right; // 注意这里是可以改变的
	if (GetNext(pNode) == NULL)
	{
		cout << "我是空,没有指向的值!" << endl;
	}
	else
	{
		cout << GetNext(pNode)->val << endl;
	}
	
	system("pause");
	return;
}
/*  当输入的结点是8时,
2 3 4 5 6 7 8
我是空,没有指向的值!
请按任意键继续. . .
*/
/* 当输入结点为5时
2 3 4 5 6 7 8
6
请按任意键继续. . .
*/

一定还有不引入vector的方法,to be continued…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值