二叉树的基本操作

这篇博客回顾了二叉树的相关知识,包括定义、创建、遍历(先序、中序、后序、层次)、序列化与反序列化、求最大深度、查找所有路径等操作,并给出了具体实现。此外,还介绍了如何根据中序和后序序列重建二叉树的问题。这些内容对于理解和解决二叉树问题非常有帮助。
摘要由CSDN通过智能技术生成

数据结构的一些知识很久没碰了,忘得差不多了都,来回顾总结一下,本篇先写一下二叉树相关的一些操作。

二叉树定义

struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

二叉树的创建

通过输入先序二叉树序列创建二叉树,用'#'字符代表空节点。

//通过先序输入创建二叉树
TreeNode* CreateTreeByInput()
{
	char ch;
	std::cin >> ch;
	if (ch == '#')
		return NULL;//输入#表示创建结束
	TreeNode* root = new TreeNode(ch);
	root->left = CreateTreeByInput();
	root->right = CreateTreeByInput();
	return root;
}

二叉树的遍历

先序、中序、后序三种基本遍历方式。

//先序遍历
void PreOrder(TreeNode* root)
{
	if (root == NULL)return;
	std::cout << (char)root->val << ' ';
	PreOrder(root->left);
	PreOrder(root->right);
}
//中序遍历
void InOrder(TreeNode* root)
{
	if (root == NULL)return;
	PreOrder(root->left);
	std::cout << (char)root->val << ' ';
	PreOrder(root->right);
}
//后序遍历
void PostOrder(TreeNode* root)
{
	if (root == NULL)return;
	std::cout << (char)root->val << ' ';
	PreOrder(root->left);
	PreOrder(root->right);
}

还有一种层次遍历方式,从上往下逐层遍历,需要借助队列实现,每次将父结点出队,子结点进队即可。

//层次遍历
void levelOrder(TreeNode* root)
{
	if (root == NULL)return;
	queue<TreeNode*> q;
	q.push(root);
	while (!q.empty())
	{
		TreeNode* now = q.front();
		cout << (char)now->val << ' ';
		if (now->left != NULL)q.push(now->left);
		if (now->right != NULL)q.push(now->right);
		q.pop();
	}
}

LeetCode上一道题目:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/,要求得到自底向上的层次遍历序列,只需要先按层次遍历得到序列,然后用头插法插入最终集合即可。

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> result;
        if(root==NULL)return result;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            vector<int> level;
            int cnt=q.size();
            for(int i=0;i<cnt;i++)
            {
                TreeNode* node=q.front();
                q.pop();
                level.push_back(node->val);
                if(node->left!=NULL)q.push(node->left);
                if(node->right!=NULL)q.push(node->right);
            }
            result.insert(result.begin(),level);
        }
        return result;
    }
};

二叉树序列化与反序列化

序列化就是指将二叉树转换成一个序列(比如字符串),反序列化就是将转换的序列还原成二叉树。

序列化

没啥好说的,按照先序遍历依次写入字符串。

//序列化二叉树(先序),结果保存在str中
void Serialize(TreeNode* root, std::string& str)
{
	if (root == NULL)
	{
		str += "#";
		return;
	}
	str += (char)root->val;
	Serialize(root->left, str);
	Serialize(root->right, str);
}
反序列化

反序列化就是按照先序遍历创建的同时,用index索引来从字符串中读取当前结点对应字符。

//反序列化方法(先序)
TreeNode* Deserialize(const std::string str, int& index)
{
	if (str == "" && index >= str.size())return NULL;
	if (str[index] == '#')
	{
		index++;
		return NULL;
	}
	TreeNode* root = new TreeNode(str[index++]);
	root->left = Deserialize(str, index);
	root->right = Deserialize(str, index);
	return root;
}

//调用反序列化
	string str = "akjl#####";
	int index = 0;
	TreeNode* root=Deserialize(str, index);

求二叉树最大深度(层数)

//二叉树最大深度
int MaxDepth(TreeNode* root)
{
	if (root == NULL)return 0;
	return max(MaxDepth(root->left), MaxDepth(root->right)) + 1;
}

二叉树所有路径

题目:https://leetcode-cn.com/problems/binary-tree-paths/ ,深搜完事,碰到叶子结点就说明找到一条路径,加入结果集合,否则就继续搜。

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> res;
        dfs(root,"",res);
        return res;
    }

    void dfs(TreeNode* root,string str,vector<string> &res)
    {
        if(root!=NULL)
        {
            str+=to_string(root->val);
            if(root->left==NULL&&root->right==NULL)
            {
                res.push_back(str);return;
            }
            dfs(root->left,str+"->",res);
            dfs(root->right,str+"->",res);
        }
    }
};

从中序序列和另一序列重建二叉树

根据中序序列再加上先序、后序、层次中的任何一种序列就能重新构建出唯一的二叉树,此处以中序加后序为例,

后序序列的最后一个必定为根结点,那么只要在中序序列中找到这个根结点,左边就是左子树,右边就是右子树,递归创建即可。

题目:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        TreeNode* root=create(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
        return root;
    }

    TreeNode* create(vector<int>& inorder,vector<int>& postorder,int inL,int inR,int postL,int postR){
        if(postL>postR)return NULL;
        
        TreeNode* root=new TreeNode(postorder[postR]);

        int i=inL;
        for(;i<=inR;i++){
            if(inorder[i]==postorder[postR])break;
        }
        int numLeft=i-inL;

        root->left=create(inorder,postorder,inL,i-1,postL,postL+numLeft-1);
        root->right=create(inorder,postorder,i+1,inR,postL+numLeft,postR-1);

        return root;
    }
};
二叉树是一种非常重要的数据结构,它的基本操作包括创建、销毁、遍历、查找等。下面是二叉树基本操作的实现方法: 1. 创建二叉树:通过前序遍历的数组构建二叉树,其中 '#' 表示空节点。具体实现方法可以参考引用中的 BinaryTreeCreate 函数。 2. 销毁二叉树:遍历二叉树,依次释放每个节点的内存空间。具体实现方法可以参考引用中的 BinaryTreeDestory 函数。 3. 遍历二叉树二叉树的遍历包括前序遍历、中序遍历、后序遍历和层序遍历。具体实现方法可以参考引用中的 BinaryTreePrevOrder、BinaryTreeInOrder、BinaryTreePostOrder 和 BinaryTreeLevelOrder 函数。 4. 查找二叉树节点:在二叉树中查找值为 x 的节点,具体实现方法可以参考引用中的 BinaryTreeFind 函数。 5. 计算二叉树节点个数:计算二叉树中节点的个数,具体实现方法可以参考引用[2]中的 BinaryTreeSize 函数。 6. 计算二叉树叶子节点个数:计算二叉树中叶子节点的个数,具体实现方法可以参考引用中的 BinaryTreeLeafSize 函数。 7. 计算二叉树第 k 层节点个数:计算二叉树中第 k 层节点的个数,具体实现方法可以参考引用中的 BinaryTreeLevelKSize 函数。 8. 判断二叉树是否是完全二叉树:判断二叉树是否是完全二叉树,具体实现方法可以参考引用中的 BinaryTreeComplete 函数。 9. 计算二叉树的深度:计算二叉树的深度,具体实现方法可以参考引用中的 BinaryTreeDeep 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值