非递归版本讲解:代码随想录
144. 二叉树的前序遍历:力扣
94. 二叉树的中序遍历:力扣
145. 二叉树的后序遍历:力扣
二叉树:
二叉搜索树:二叉搜索树是一个有序树。
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉排序树
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作时间时间复杂度是logn,注意我这里没有说unordered_map、unordered_set,unordered_map、unordered_map底层实现是哈希表。
二叉树的遍历:
- 深度优先遍历
- 前序遍历(递归法,迭代法):中左右
- 中序遍历(递归法,迭代法):左中右
- 后序遍历(递归法,迭代法):左右中
- 广度优先遍历
- 层次遍历(迭代法)
前中后指的就是中间节点的遍历顺序!
递归写法
- 确定递归函数的参数和返回值
- 确定递归的终止条件
- 确定单层递归的逻辑
void traversal(cur, vec){
if(cur == nullptr) return;
vec.push(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec);// 右
}
非递归写法:
栈模拟递归
前序:中左右
入栈时根据需要反向入栈:入栈的时候先给栈中存入右孩子节点,再存入左孩子结点,这样弹出时可以先弹出左再弹出右。
后序遍历 :左右中
前序遍历结果反向
中序遍历:左中右
中序遍历和前后序不同,因为根节点(中间节点)是在中间访问,也即访问顺序和遍历顺序不同。
访问时先访问5 - 4 - 1,遍历顺序是1 - 4 - 5
用栈模拟过程
- 根节点入栈,左孩子入栈,直到左孩子为空
- pop出栈顶元素,访问栈顶节点,栈顶节点的右孩子入栈,右孩子的左孩子持续入栈,直到左孩子为空
- 即每次有节点入栈时,循环将节点的左孩子节点入栈
- 每次有节点出栈时,先访问该节点,再将节点的右孩子节点入栈(也要循环将右孩子的左孩子节点入栈)
144. 二叉树的前序遍历
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
if(root == nullptr) return res;
st.push(root); // 根节点入栈
TreeNode* node = nullptr;
while(!st.empty()){
node = st.top();
st.pop(); // 栈顶元素出栈
res.push_back(node->val);
if(node->right != nullptr) st.push(node->right);
if(node->left != nullptr) st.push(node->left);
}
return res;
}
};
94. 二叉树的中序遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (root == nullptr) return res;
TreeNode* temp = root;
st.push(root);
while(temp->left != nullptr){ // 节点的左孩子循环入栈
st.push(temp->left);
temp = temp->left;
}
while(!st.empty()){
temp = st.top();
st.pop();
res.push_back(temp->val);
if(temp->right != nullptr){ // 访问节点后节点的右孩子入栈
st.push(temp->right);
temp = temp->right;
while(temp->left != nullptr){ // 节点的左孩子循环入栈
st.push(temp->left);
temp = temp->left;
}
}
}
return res;
}
};
145. 二叉树的后序遍历
前序遍历是中左右,后序遍历是左右中,reverse之后是中右左,和前序不完全相同
左孩子先入栈,出栈时右孩子先出栈。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if(root == nullptr) return res;
st.push(root);
TreeNode* node;
while(!st.empty()){
node = st.top();
res.push_back(node->val); // 中
st.pop();
if(node->left != nullptr) st.push(node->left); // 左
if(node->right != nullptr) st.push(node->right); // 右
}
reverse(res.begin(), res.end()); // 中右左 -> 左右中
return res;
}
};
统一写法
todo:代码随想录