理论基础
种类
-
满二叉树
- 除了最后一层, 其余节点都是满的
-
完全二叉树
- 除了最后一层没满, 并且是从左到右
- 大根堆或小根堆
-
二叉搜索树
- 时间复杂度O(logn)
- 元素有一定顺序, 结构没要求
-
平衡二叉搜索树
- 左子树和右子树的高度差不能超过1
- map、set、multimap和multiset底层是由平衡二叉搜索树实现的, 所以一定是有序的
存储方式
-
链式存储
-
顺序存储
遍历方式
-
深度优先遍历
- 前序遍历(递归法,迭代法)
- 中序遍历(递归法,迭代法)
- 后序遍历(递归法,迭代法)
-
广度优先遍历
- 层次遍历(迭代法)
定义
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
/* 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) {}
* };
*/
递归遍历
递归的三要素
- 确定递归函数的参数和返回值
- 终止条件
- 单层递归逻辑
例题:
144.二叉树的前序遍历
145.二叉树的后序遍历
94.二叉树的中序遍历
实现
class Solution {
public:
//前序遍历
void preorder(TreeNode* root, vector<int>& result) {
if (root == nullptr) return;
result.push_back(root->val);
preorder(root->left, result);
preorder(root->right, result);
}
//中序遍历
void inorder(){
if (root == nullptr) return;
preorder(root->left, result);
result.push_back(root->val);
preorder(root->right, result);
}
//后序遍历
void postorder(TreeNode* root, vector<int>& result) {
if (root == nullptr) return;
preorder(root->left, result);
preorder(root->right, result);
result.push_back(root->val);
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
preorder(root, result);
return result;
}
};
迭代遍历
实现
//前序遍历时, 使用栈实现
//入栈顺序: 根 -> 右, 左 (出栈为: 根) -> 右 (出栈为: 左)-> (出栈为: 右)
//出栈结果: 根 -> 左 -> 右
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> mystack;
vector<int> result;
if (root) mystack.push(root);
while (!mystack.empty()) {
TreeNode* tem = mystack.top();
mystack.pop();
if (tem-> right) mystack.push(tem->right);
if (tem-> left) mystack.push(tem->left);
result.push_back(tem->val);
}
return result;
}
//后序遍历为: 根 左 右
//根 左 右 -> 根 右 左 -> 左 右 根
//调换两次顺序即可实现
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> mystack;
vector<int> result;
if (root) mystack.push(root);
while (!mystack.empty()) {
TreeNode* tem = mystack.top();
mystack.pop();
if (tem-> left) mystack.push(tem->left);
if (tem-> right) mystack.push(tem->right);
result.push_back(tem->val);
}
reverse(result.begin(), result.end());
return result;
}
//中序遍历
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*>mystack;
TreeNode* cur = root;
while (cur != nullptr || !mystack.empty()) {
if (cur != nullptr) {
mystack.push(cur);
cur = cur->left;
} else {
cur = mystack.top();
mystack.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
统一迭代
实现
- 依靠NULL点区分是否将下一个元素加入结果中
//前序遍历
vector<int> preorderTraversal(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); // 右
if (node->left) st.push(node->left); // 左
st.push(node); // 中
st.push(NULL);
} else {
st.pop();
node = st.top();
st.pop();
result.push_back(node->val);
}
}
return result;
}
//中序遍历
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<int> postorderTraversal(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();
st.push(node); // 中
st.push(NULL);
if (node->right) st.push(node->right); // 右
if (node->left) st.push(node->left); // 左
} else {
st.pop();
node = st.top();
st.pop();
result.push_back(node->val);
}
}
return result;
}