先记录一下群里大佬分享对“维护”这个词的理解。维护就是说保护一个数据结构,让它本身的性质不发生变化,以单调队列为例子,维护单调队列就是让pop的时候只删去当前的队首(最大值),push之前把队内已有元素中小于即将加入的元素先去掉,然后再加入。
一、二叉树的基础部分
二叉树种类:
1.满二叉树:特征为要么子节点全满为2,要么没有子节点了。求满二叉树的节点数:2*k-1(k为深度,从1开始计数)
2.完全二叉树:特征是除了最底层可以不满,其他层都是满节点,并且在底层的节点必须是连续的。
3.二叉搜索树:特征是,所有左子树(包括左节点)小于根节点,所有右子树(包括右节点)大于根节点。寻找其中一个元素的时间复杂度是O(logn)。二叉搜索树对节点的结构布局没有要求,但是对节点内元素的排序有要求。必须满足左<中<右的情况。
4.平衡二叉搜索树:特征是,左子树和右子树二者高度差的绝对值不能大于1(也就是<=1)。插入,查找其中一个元素的时间复杂度都是O(logn)。STL中map、set、multimap、multiset的底层实现都是平衡二叉搜索树。
二叉树存储方式:
1.链式存储:每个节点留两个指针,一个指向左孩子,一个指向右孩子。
2.线性储存:用一个数组来保存每个节点中的值,其中左孩子=2i+1 右孩子=2i+2
二叉树的遍历:
深度优先搜索:所说的前序遍历(中左右)、中序遍历(左中右)、后序遍历(左右中)(前中后序遍历其实是指“中”的位置)都是深度优先搜索,可以用递归实现,也可以用迭代法来实现。
广度优先搜索:层序遍历,用迭代法、创建队列来实现
二叉树的定义:
struct tree{
int val;
tree*left;
tree*right;
tree(val): val(val),left(null),right(null){ }
};
二、前序遍历:
递归方法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void traversal(TreeNode*cur,vector<int>&result){
if(cur==nullptr) return;
result.push_back(cur->val);
traversal(cur->left,result);
traversal(cur->right,result);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root,result);
return result;
}
};
非递归迭代方法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>st;
vector<int>result;
if(root==NULL)return result;
st.push(root);
while(!st.empty()){
TreeNode*temp=st.top();
result.push_back(temp->val);
st.pop();
if(temp->right)st.push(temp->right);
if(temp->left)st.push(temp->left);
}
return result;
}
};
三、后序遍历
递归方法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void traversal(TreeNode*cur,vector<int>&result){
if(cur==nullptr)return ;
traversal(cur->left,result);
traversal(cur->right,result);
result.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root,result);
return result;
}
};
非递归迭代方法:
注意这里目标是左右中遍历,但实际上只能做到中右左,所以在操作的时候先让左侧节点入栈,最后要加个reverse函数倒转顺序才是左右中。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>st;
if(root==nullptr)return result;
st.push(root);
while(!st.empty()){
TreeNode*temp=st.top();
st.pop();
result.push_back(temp->val);
if(temp->left)st.push(temp->left);
if(temp->right)st.push(temp->right);
}
reverse(result.begin(),result.end());
return result;
}
};
四、中序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void traversal(TreeNode*cur,vector<int>&result){
if(cur==nullptr)return;
traversal(cur->left,result);
result.push_back(cur->val);
traversal(cur->right,result);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
traversal(root,result);
return result;
}
};
非递归迭代方法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int>result;
stack<TreeNode*>st;
if(root==nullptr)return result;
TreeNode*cur=root;
while(cur!=nullptr||!st.empty()){
if(cur!=nullptr){
st.push(cur);
cur=cur->left;
}
else{
cur=st.top();
st.pop();
result.push_back(cur->val);
cur=cur->right;
}
}
return result;
}
};
五、层序遍历(广度优先搜索)
定义一个队列,让每层节点的指针进入和弹出。定义一个变化的size等于队列大小,这个大小将用于控制每次访问的节点数。访问队列(录入一维数组、弹出、其左节点指针进入队列、右节点指针进入队列)反复循环。while的条件控制为队列不为空,也就是说,所有节点都访问完了,才回出现队列为空的情况,正是我想要的条件。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*>que;
int size;
if(root!=nullptr){
que.push(root);
}
vector<vector<int>>result;
while(!que.empty()){
size=que.size();
vector<int>vec;
for(int i=0;i<size;i++){
TreeNode*temp=que.front();
que.pop();
vec.push_back(temp->val);
if(temp->left!=nullptr){
que.push(temp->left);
}
if(temp->right!=nullptr){
que.push(temp->right);
}
}
result.push_back(vec);
}
return result;
}
};