今天的话就是复习了一下简单的二叉树的遍历,之前是做过的,但是感觉过了好久遗忘了不少,大概内容还记得但是具体细节很难想起来,代码敲出来还是半对不对的,今天还知道了一个用vector建立一维数组的方法即下:
vector<int> v
声明了一个一维的动态数组。动态数组是一个可变大小的数组,可以通过 push_back
等方法在数组末尾添加元素,并且支持动态地调整大小。 vector
类型实现了动态数组的功能,并提供了许多其他实用的功能,例如数组的排序、查找等。
今天对auto的影响也加深了,就是让系统自己给你定义一个符合后面数值的类型。
回顾正题,对于二叉树的遍历,大致分为先序遍历,中序遍历,后序遍历,分别为中左右,左中右,左右中。其名字称呼就是随着中间结点的位置进行改变的。其函数方式懂一便能推二。
对于遍历的方式的话代码稍少感觉是给人更简单的就是递归如下:
class Solution {
public:
vector<int> v;
vector<int> preorderTraversal(TreeNode* root)
{
if(root != nullptr)
{
v.push_back(root->val); //关于递归用法
preorderTraversal(root->left);
preorderTraversal(root->right);
}
return v;
}
};
class Solution {
public:
vector<int> v;
vector<int> postorderTraversal(TreeNode* root)
{
if(root != nullptr)
{
postorderTraversal(root->left);
postorderTraversal(root->right); //后序遍历依葫芦画瓢
v.push_back(root->val);
}
return v;
}
};
对于非递归算法的话就是迭代法用栈,就拿先序遍历举个例子,中左右,先建立一个关于树节点的栈,对于栈而言就是先进后出,所以一开始对于根节点必须出栈,让其直接放在数组里。对于叶子结点的话,对于入栈操作,都是先放入右孩子再放入左孩子,因为有依据先进后出的这么一个操作,代码如下
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> ans;
if (root == nullptr)
//若树为空,则直接返回
return ans;
s.push(root);
while (!s.empty()) {
TreeNode* p = s.top();
s.pop();
ans.push_back(p->val);
if (p->right) {
//前序遍历为根左右,按照栈先进后出的特性,所以先将右节点入栈
s.push(p->right);
}
if (p->left) {
//前序遍历为根左右,按照栈先进后出的特性,所以后将左节点入栈
s.push(p->left);
}
}
return ans;
}
};
但是对于非递归而言,中序遍历的话必须先将左子树遍历完,再遍历右子树。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
vector<int> ans;
if (root == nullptr)
//若树为空,则直接返回
return ans;
TreeNode* p = root;
while (p != nullptr || !s.empty()) {
//先将所有左子树入栈
while (p != nullptr) { //中序·
s.push(p);
p = p->left;
}
p = s.top();
s.pop();
ans.push_back(p->val);
p = p->right;
}
return ans;
}
};
主要对应的就是力扣上的144 145 94三个题
今天还了解了一下二叉搜索树的概念就是:所有的根节点大于左子树的节点,小于右子树的节点的二叉树就叫做二叉搜索树。但是其余操作还没有细看没有深度了解。