二叉树
文章链接:代码随想录-二叉树
细节基础就不多赘述,主要关注满二叉树、完美二叉树。
存储方式:链式、数组(用于完美二叉树,堆)。
递归遍历
文章链接:代码随想录-递归遍历
前序遍历:
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec) {
if (cur == NULL) return;
vec.push_back(cur->val); // 中
traversal(cur->left, vec); // 左
traversal(cur->right, vec); // 右
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
后续的就调整顺序即可。
递归注意:
1. 递归终止条件;
2. 递归函数传递的参数与返回;
3. 递归调用顺序。
迭代遍历
文章链接:迭代遍历
前序遍历
注意,对每个节点操作分为两个:
访问:遍历到改点;
处理:将值放到res数组中。
迭代,使用栈模拟递归。
前序遍历则是中左右,先将中放入栈,然后出栈,处理,将它的右节点、左节点按照顺序入栈,这样保证深度遍历顺序。
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> sta;
vector<int> res;
if(root == NULL) return res;
sta.push(root);
while(!sta.empty())
{
TreeNode* p = sta.top();
res.push_back(p->val);
sta.pop();
if(p->right) sta.push(p->right);
if(p->left) sta.push(p->left);
}
return res;
}
中序遍历
与前序遍历不同,中序遍历中访问和处理的不是同一个元素,中会先被访问,但后面才处理,所以要先将它压栈,这是就需要指针来遍历,充当访问,出栈则是处理。
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> sta;
if(root == NULL) return res;
TreeNode* cur = root;
while(!sta.empty() || cur != NULL)
{
if(cur != NULL)
{
sta.push(cur);
cur = cur->left;//一直将左边元素放进栈里
}
else
{
cur = sta.top();
res.push_back(cur->val);
sta.pop();
cur = cur->right; //开始看最底层的右侧。
}
}
return res;
}
这里要注意一直放“左节点”直至NULL,然后可以处理top()元素,然后进入right节点。
后序遍历
将前序遍历中左右顺序调换,然后颠倒输出res即可。
统一遍历
这就是将前序、后序变为中序的模式,不过添加"NULL”来分辨“中节点”是否已处理!!
中序遍历:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
if (root != NULL) st.push(root);
while (!st.empty()) {
TreeNode* node = st.top();
if (node != NULL) {
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
if (node->right) st.push(node->right); // 添加右节点(空节点不入栈)
st.push(node); // 添加中节点
st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。
if (node->left) st.push(node->left); // 添加左节点(空节点不入栈)
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
st.pop(); // 将空节点弹出
node = st.top(); // 重新取出栈中元素
st.pop();
result.push_back(node->val); // 加入到结果集
}
}
return result;
}
前序、后序都只需要改变添加节点的操作就好。
处理与访问要分开,这是为了防止重复遍历!!
层次遍历
文章链接:代码随想录-层次遍历
借助队列数据结构实现先进先出,然后层层访问。
模版:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
return result;
}
这部分题很多,不详尽介绍了,都是变体。