四、二叉树

树是常用的数据存储方式,由于树中存在大量的指针结构,所以树的有关操作相对来说是比较难的。

一、 树的定义

这里用二叉树来举例子

复制代码
使用结构体的方式实现二叉树:
struct BinaryTreeNode {
	int data;
	BinartTreeNode* left;
	BinartTreeNode* right;
};

使用类的方式实验二叉树:
class BinaryTreeNode {
public:
	int data;
	BinaryTreeNode *left;
	BinaryTreeNode* right
	BinaryTreeNode(int value) : data(value), left(nullptr), right(nullptr) { }
};

二、二叉树的前、中、后序遍历

前序遍历:根左右

中序遍历:左跟右

后序遍历:左右根

2.1 前序遍历

2.1.1 递归形式实现前序遍历

c++ 复制代码
class Solution{
public:
	void preorder(TreeNode *root, vector<int> &res){
		if (root == nullptr){
			return;
		}
		res.push_back(root->val);
		preorder(root->left, res);
		preorder(root->right, res);
	}
	vector<int> preorderTraversal(TreeNode *root){
		vector<int> res;
		preorder(root, res);
		return res;
	}
};

2.1.2 迭代形式实现前序遍历

c++ 复制代码
class Solution{
public:
    vector<int> preorderTraversal(TreeNode* root){
        vector<int> res;
        if (root == nullptr){
            return res;
        }
        stack<TreeNode*> stk;//创建一个栈
        TreeNode* node =root;//创建一个树节点
        while (!stk.empty() || node != nullptr){
            while(node != nullptr){//只要节点有左子树,就进行这一步骤
                res.emplace_back(node->val);//节点的值存入res
                stk.emplace(node);//节点存入栈中
                node = node->left;
            }
            node = stk.top();
            stk.pop();
            node = node->right;
        }
        return res;
    }
};

2.2 中序遍历

2.2.1 递归形式的中序遍历

先找左子树,左子树没有了,存储当前节点,再找右子树

c++ 复制代码
class Solution {
public:
    void midorder(TreeNode *root, vector<int> &res){
        if (root == nullptr){
            return;
        }
        midorder(root->left, res);
        res.push_back(root->val);
        midorder(root->right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        midorder(root, res);
        return res;
    }
};

2.2.2 迭代形式的中序遍历

c++ 复制代码
class Solution{
public:
    vector<int> inorderTraversal(TreeNode* root){
        vector<int> res;
        if(root == nullptr) return res;
        stack<TreeNode*> stk;
        TreeNode* node = root;
        while (!stk.empty() || node != nullptr){
            while (node != nullptr){
                stk.emplace(node);
                node = node->left;
            }
        node = stk.top();
        stk.pop();
        res.push_back(node->val);
        node = node->right;
        }
        return res;
    }
};

2.3 后序遍历

2.3.1 递归形式的后序遍历

c++ 复制代码
class Solution {
public:
    void lastorder(TreeNode* root, vector<int> &res)
    {
        if (root==nullptr) return;
        lastorder(root->left, res);
        lastorder(root->right, res);
        res.push_back(root->val);
    }
        vector<int> postorderTraversal(TreeNode*root) 
    {
        vector<int> res;
        lastorder(root, res);
        return res;
    }
};

2.3.2 迭代形式的后序遍历

c++ 复制代码
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if (root == nullptr){
            return res;
        }
        stack<TreeNode *> stk;
        TreeNode *prev = nullptr;
        while (root != nullptr || !stk.empty()){
            while (root != nullptr){
                stk.emplace(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            if (root->right == nullptr || root->right == prev){
                res.emplace_back(root->val);
                prev = root;
                root = nullptr;
            }
            else{
                stk.emplace(root);
                root = root->right;
            }
        }
        return res;
    }
};

2.4 根据前序遍历构造二叉搜索树


这道题目是有一些难度的,首先需要弄明白原理,根据题目的分析,首先第一个节点是根节点(称其为root),第一个比根节点大的,就是根节点的右子树(称其为Rchild),那么root和Rchild之间的成员,一定是根节点左子树或左子树的孩子。其中的第一个,就是根节点的左子树。

那么根据上面的思想,可以写出伪代码

c++ 复制代码
TreeNode* fun(vector<int>& preorder, int left, int right){
	if (left>right) return nullptr;
	int root = preorder[left];
	int mid = left;
	for(; mid<=right; mid++){
		if(preorder[mid]>root) break;
	}
	TreeNode *node = new TreeNode(root);
	node->left = fun(vector<int>& preorder, int left+1, int mid-1)
	node->right = fun(vector<int>& preorder, int mid, int right)
	return node;
}

上面的代码还是挺难想的,必须清楚的考虑边界条件才能写对,了解一下吧

相关推荐
牛油果子哥q2 小时前
C++内存模型与深浅拷贝万字详解:栈堆静态内存布局、深浅拷贝底层差异、内存泄漏根治、拷贝崩溃踩坑、手写深拷贝实战
java·开发语言·c++
大鹏的NLP博客2 小时前
通用 Linux 嵌入式板端 C/C++ ABI 与 Glibc 依赖治理规范
linux·c++·交叉编译
ysa0510302 小时前
c++常用自带函数用法与注意
c++·笔记·算法
鸿芯微控科技7 小时前
MFC模拟量信号异常怎么排查?0-5V、4-20mA接线与量程换算
c++·5g·mfc·故障排查·质量流量控制器·4-20ma·模拟量信号
三十岁老牛再出发7 小时前
08.18每日总结
c++·python·numpy·pandas
余额瞒着我当琳8 小时前
C++--vector底层,leetcode118杨辉三角实战,对于传统reserve的坑点,迭代器失效
开发语言·c++
醉城夜风~8 小时前
(超详细)C++多态(Polymorphism)
开发语言·c++
小小龙学IT9 小时前
现代 C++ 内存管理与资源安全深度解析:从 RAII 到所有权模型
c++·安全
欧特克_Glodon9 小时前
OpenCV计算机视觉开发入门与实践<十三>:图像转换之灰度图、二值图
c++·人工智能·opencv·计算机视觉
神仙别闹9 小时前
基于C++ MFC实现动态分区分配存储管理
开发语言·c++·mfc