1.前序遍历:根—左—右,单栈
vector<int> preorderTraversal(TreeNode* root) {
// 方法一:递归
// vector<int> res;
// traversal(root,res);
// return res;
// 方法二:迭代
vector<int> res;
if(root == nullptr)
return res;
stack<TreeNode*> tra;
// 先压入根节点
tra.push(root);
while(!tra.empty())
{
// 弹出(打印)节点的同时,分别压入右孩子和左孩子
TreeNode* temp = tra.top();
res.push_back(temp->val);
tra.pop();
// 右孩子
if(temp->right != nullptr)
tra.push(temp->right);
// 左孩子
if(temp->left != nullptr)
tra.push(temp->left);
}
return res;
}
2.中序遍历:左—根—右,单栈
vector<int> inorderTraversal(TreeNode* root) {
// 方法一:递归
// vector<int> res;
// if(root ==nullptr)
// return res;
// inorderTraversal(root,res);
// return res;
// 方法二:迭代
vector<int> res;
if(root == nullptr)
return res;
stack<TreeNode*> tra;
TreeNode* node = root;
// !(A && B) 就是 (!A || !B)
while( node != nullptr || !tra.empty() )
{
// 向左一直入栈,直到为空,则打印栈顶元素
while(node != nullptr)
{
tra.push(node);
node = node->left;
}
// 弹出栈顶元素,并令node更新为栈顶右孩子
TreeNode* temp = tra.top();
tra.pop();
res.push_back(temp->val);
node = temp->right;
}
return res;
}
3.后序遍历:左—右—根,双栈或者单栈
// 方法一:递归
// vector<int> res;
// if(root == nullptr)
// return res;
// traversal(root, res);
// return res;
// //方法二:迭代,双栈
// vector<int> res;
// if(!root)
// return res;
// stack<TreeNode*>mystack1;
// stack<TreeNode*>mystack2;
// mystack1.push(root);
// while(!mystack1.empty())
// {
// // mystack1每弹出一个节点,则分别压入其左孩子和右孩子,并将弹出的节点压入mystack2
// TreeNode* node = mystack1.top();
// mystack1.pop();
// mystack2.push(node);
// // 左孩子
// if(node->left)
// mystack1.push(node->left);
// // 右孩子
// if(node->right)
// mystack1.push(node->right);
// }
// while(!mystack2.empty())
// {
// res.push_back(mystack2.top()->val);
// mystack2.pop();
// }
// return res;
// 方法三:单栈
vector<int> res;
if(!root)
return res;
stack<TreeNode*>mystack;
mystack.push(root);
// 上一次弹出的节点,表示已经处理过的
TreeNode* pre = root;
// 当前栈顶节点
TreeNode* cur = nullptr;
while(!mystack.empty())
{
cur = mystack.top();
// 左子树和右子树都没被处理过
if(cur->left != nullptr && pre != cur->left && pre != cur->right)
{
mystack.push(cur->left);
}
// 右子树没被处理过
else if(cur->right != nullptr && pre != cur->right)
{
mystack.push(cur->right);
}
// 到了叶子节点,或者左右子树都被处理过,则弹出,并更新pre
else
{
mystack.pop();
res.push_back(cur->val);
pre = cur;
}
}
return res;
}
4.层序遍历:bfs,队列queue
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
if(root == nullptr)return res;
queue<TreeNode*> queues;
queues.push(root);
int nextlevel = 0;
int current = 1;
while(!queues.empty())
{
vector<int> col;
while(current>0)
{
TreeNode* temp = queues.front();
col.push_back(temp->val);
queues.pop();
--current;
if(temp->left != nullptr)
{
queues.push(temp->left);
++nextlevel;
}
if(temp->right != nullptr)
{
queues.push(temp->right);
++nextlevel;
}
}
res.push_back(col);
current = nextlevel;
nextlevel = 0;
}
return res;
}
5.之字形按层打印,用到双栈stack<TreeNode*> PerRow[2] 和数组标志flag
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> res;
if(root == nullptr)
return res;
stack<TreeNode*> PerRow[2];
PerRow[0].push(root);
int flag = 0;
int currow = 1;//当前行节点数
int nextrow = 0;//下一行节点数
while(!PerRow[0].empty() || !PerRow[1].empty())
{
vector<int> col;
while(currow>0)
{
TreeNode* temp = PerRow[flag].top();
col.push_back(temp->val);
PerRow[flag].pop();
--currow;
// 开始flag == 0,那么下一次循环flag == 1
// 下一行是偶数行,从右到左打印,所以从左到右压入
if(flag == 0)
{
if(temp->left != nullptr)
{
PerRow[1].push(temp->left);
++nextrow;
}
if(temp->right != nullptr)
{
PerRow[1].push(temp->right);
++nextrow;
}
}
// 下一行是奇数行,从左到右打印,所以从右到左压入
if(flag == 1)
{
if(temp->right != nullptr)
{
PerRow[0].push(temp->right);
++nextrow;
}
if(temp->left != nullptr)
{
PerRow[0].push(temp->left);
++nextrow;
}
}
}
//更新当前行、下一行、flag等
currow = nextrow;
res.push_back(col);
flag = 1-flag;
nextrow = 0;
}
return res;