二叉树
二叉树的理论知识
二叉树的种类
满二叉树
满二叉树:如果一棵二叉树只有度为0的节点和度为2的节点,并且度为0的节点在同一层,则此二叉树为满二叉树(深度为k,有2^k-1个节点的二叉树)。
完全二叉树
在完全二叉树中,除了底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的位置。
优先级队列其实是一个堆,堆就是一棵完全二叉树,同时保证父子节点的顺序关系。
二叉搜索树
二叉搜索数是一个有序树
- 若左子树不空,则左子树上所有结点的值均小于根节点的值;
- 若右子树不空,则右子树上所有结点的值均大于根节点的值;
- 它的左,右子树也分别为二叉排序树
中序遍历二叉搜索树得到的数组是一个递增数组
平衡二叉搜索树
它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
注:c++中map,set,multimap,multiset的底层实现都是平衡二叉树,所以map,set的增删操作时间复杂度是logn。(比如构造set的过程中,插入的数据必须满足红黑树的规则,因此会不断进行调整,确保最后生成的set中的数据是有序的)
#include <iostream>
#include <set>
int main() {
std::set<int> mySet;
// 插入一些元素
mySet.insert(10);
mySet.insert(20);
mySet.insert(15);
mySet.insert(5);
mySet.insert(1);
// 输出 set 中的元素
for (int x : mySet) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
map、set、multimap 和 multiset 的底层实现使用平衡二叉树(如红黑树),以保证在对数时间复杂度内完成插入、删除和查找操作。通过使用红黑树,这些容器能够有效地管理有序数据,并提供高效的操作性能。
二叉树的存储方式
二叉树可以链式存储,也可以顺序存储
链式存储方式用指针,顺序存储用数组
二叉树的遍历方式
二叉树主要有两种遍历方式,深度优先遍历和广度优先遍历
- 深度优先遍历
前序遍历(根左右,递归法和迭代法)
中序遍历(左根右,递归法和迭代法)
后序遍历(左右根,递归法和迭代法)
注:栈是递归的一种实现结构,深度优先遍历可以借助栈用递归的方式来实现 - 广度优先遍历
层次遍历(迭代法)
注:广度优先遍历一般用队列实现
二叉树的实现
链式存储二叉树节点的定义方式
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL){
}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right){
}
};
二叉树相关的力扣题
二叉树的递归遍历和迭代遍历
二叉树的前序遍历
题目
递归遍历
class Solution {
public:
void traversal(TreeNode* cur, vector<int>& vec)
{
if (cur == nullptr)
{
return;
}
vec.push_back(cur->val);
traversal(cur->left, vec);
traversal(cur->right, vec);
}
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> res;
traversal(root, res);
return res;
}
};
迭代遍历
用栈实现
class Solution
{
public:
vector<int> preorderTraversal(TreeNode* root)
{
if (root == nullptr)
{
return {
};
}
vector<int> res;
stack<TreeNode *> st;
st.push(root);
while(!st.empty())
{
TreeNode *cur = st.top();
st.pop();
res.push_back(cur->val);
if (cur->right)
{
st.push(cur->right);
}
if(cur->left)
{
st.push(cur->left);
}
}
return res;
}
};
二叉树的后序遍历
题目
递归
class Solution
{
public:
void traversal(TreeNode *cur, vector<int>& vec)
{
if (cur == nullptr)
{
return;
}
traversal(cur->left, vec);
traversal(cur->right, vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> res;
traversal(root, res);
return res;
}
};
迭代
class Solution
{
public:
vector<int> postorderTraversal(TreeNode* root)
{
stack<TreeNode *> st;
vector<int> vec;
if (root == nullptr)
{
return{
};
}
st.push(root);
while(!st.empty())
{
TreeNode *cur = st.top();
vec.push_back(cur->val);
st.pop();
if (cur->left)
{
st.push(cur->left);
}
if (cur->right)
{
st.push(cur->right);
}
}
reverse(vec.begin(), vec.end());
return vec;
}
};
二叉树的中序遍历(*)
题目
递归
class Solution {
public:
void traversal(TreeNode *cur, vector<int>& res)
{
if(cur == nullptr)
{
return;
}
traversal(cur->left, res);
res.push_back(cur->val);
traversal(cur->right, res);
}
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> res;
traversal(root, res);
return res;
}
};
迭代
class Solution
{
public:
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> res;
stack<TreeNode *> st;
TreeNode *cur = root;
while(cur != nullptr || !st.empty())
{
if (cur != nullptr) //指针来访问节点,访问到最底层
{
st.push(cur); //将访问的节点放进栈
cur = cur->left; //左
}
else
{
cur = st.top(); //从栈里弹出的数据,就是要处理的数据
st.pop();
res.push_back(cur->val); //中
cur = cur->right;
}
}
return res;
}
};
二叉树的层序遍历
二叉树的层序遍历
class Solution
{
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
if (root == nullptr)
{
return{
};
}
vector<vector<int>> res;
queue<TreeNode *> qe;
qe.push(root);
while(!qe.empty())
{
vector<int> vec;
int size = qe.size();
while(size--)
{
TreeNode *cur = qe.front();
vec.push_back(cur->val);
qe.pop();
if (cur->left)
{
qe.push(cur->left);
}
if (cur->right)
{
qe.push(cur->right);
}
}
res.push_back(vec);
}
return res;
}
};
二叉树的层序遍历2
题目
与层序遍历1相同,只需要将结果翻转一下即可
class Solution
{
public:
vector<vector<int>> levelOrderBottom(TreeNode* root)
{
if (root == nullptr)
{
return {
};
}
vector<vector<int>> res;
queue<TreeNode *> qe;
qe.push(root);
while(!qe.empty())
{
vector<int> vec;
int size = qe.size();
while(size--)
{
TreeNode *cur = qe.front();
vec.push_back(cur->val);
qe.pop();
if (cur->left)
{
qe.push(cur->left);
}
if (cur->right)
{
qe.push(cur->right);
}
}
res.push_back(vec);
}
reverse(res.begin(), res.end());
return res;
}
};
二叉树的右视图
class Solution
{
public:
vector<int> rightSideView(TreeNode* root)
{
if (root == nullptr)
{
return{
};
}
vector<int> res;
queue<TreeNode *> qe;
qe.push(root);
while(!qe.empty())
{
TreeNode *cur = qe.front();
res.push_back(cur->val);
int size = qe.size();
while(size--)
{
TreeNode *node = qe.front();
qe.pop();
if (node->right)
{
qe.push(node->right);
}
if (node->left)
{
qe.push(node->left);
}
}
}
return res;
}
};
二叉树的层平均值
class