1、二叉树定义方式
链式存储的二叉树节点的定义方式:
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL){}
}
对比链表的定义方式:
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
2、二叉树的递归遍历
题目链接:144、前序遍历 145、后序遍历 94、中序遍历
前序遍历:
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;
}
};
后序遍历:
class Solution {
public:
void traversal(TreeNode *cur, vector<int>& vec)
{
if (cur == NULL)
{
return;
}
traversal(cur->left, vec);
traversal(cur->right, vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
中序遍历:
class Solution {
public:
void traversal(TreeNode *cur, vector<int>& vec)
{
if (cur == NULL)
{
return;
}
traversal(cur->left, vec);
vec.push_back(cur->val);
traversal(cur->right, vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
traversal(root, result);
return result;
}
};
3、迭代法
题目链接:144、前序遍历 145、后序遍历 94、中序遍历
前序遍历
先将根节点入栈,当栈不为空时进行循环,将栈顶元素出栈,并传入数组中,然后将右孩子加入栈,再加入左孩子。这样出栈时就是中左右。
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 *Node = st.top(); //中
st.pop();
result.push_back(Node->val);
if (Node->right) st.push(Node->right); //右
if (Node->left) st.push(Node->left); //左
}
return result;
}
};
2、后序遍历
前序遍历是 中左右,如果变为中右左,再翻转,就变为左右中,后序遍历。
不要忘了先把根节点传进去再去循环弹出元素。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> result;
if (root == NULL) return result;
st.push(root);
while(!st.empty())
{
TreeNode * Node = st.top();
st.pop();
result.push_back(Node->val);
if (Node->left) st.push(Node->left);
if (Node->right) st.push(Node->right);
}
reverse(result.begin(), result.end());
return result;
}
};
3、中序遍历
前序遍历,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
中序遍历,要访问的元素和要处理的元素顺序不一致,借用指针遍历来访问节点。
TreeNode * cur = root;
如果当前节点不为空,就入栈,指针指向左孩子。
如果当前节点为空,说明上一个节点的左孩子为空,令cur = st.top() 栈顶元素弹出,寻找其右孩子。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (!st.empty() || cur!= NULL)
{
if (cur != NULL)
{
st.push(cur);
cur = cur->left;
}
else
{
cur = st.top();
st.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
};