例题:将前中后序遍历用栈实现
听说递归能做的,栈也能做(因为递归通过不断调用自身,在进程栈中实现层层调用,用栈科研模拟递归调用及递归返回的过程)。
前序遍历
在前序遍历中,我们希望实现中-左-右的遍历顺序,如图,想实现前序遍历的顺序,我们可以先试试用队列试着实现,发现队列容易试出层序遍历而不是前序遍历,如例图:
我们试着用栈来模拟,根节点先入栈,当栈不为空时说明还有待处理结点,我们采用pop()操作弹出栈顶元素(即元素为5的结点)。此时将它的左右孩子入栈,这里需要注意,栈是先进后出的数据结构,若想先输出左孩子,我们需要把左孩子后入栈,把右孩子先入栈。手动模拟一遍后,得出的代码如下:
class solution{
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> result;
stack<TreeNode*> st;
st.push(root);
while (st.size() != NULL)
{
TreeNode* p = st.top();
st.pop();
result.push_back(p->val);
if (p->left) st.push(p->left);
if (p->right) st.push(p->right);
}
}
return result;
}
后序遍历
后序遍历的顺序为左-右-中,因为我们前序遍历的顺序是中-左-右,若对换入栈的顺序就能变为中-右-左,此时将得到的数组进行转置,就是想要的左-右-中遍历顺序了,代码如下:
class solution{
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> result;
stack<TreeNode*> st;
st.push(root);
while (st.size() != NULL)
{
TreeNode* p = st.top();
result.push_back(p->val);
st.pop();
if (p->left) st.push(p->left);
if (p->right) st.push(p->right);
//if (p->left) st.push(p->left);
}
reverse(result.begin(), result.end());
}
return result;
}
中序遍历
中序遍历不同于前、后序遍历,中序遍历过程中,工作结点不断往左下走直到当前指针为空,再返回上一个结点,打印出当前结点的值(最左下处叶子结点的值)。继续往右子树遍历,若当前结点指针为NULL,栈会弹出栈顶元素,记录此时的元素值后,p指针指向上一结点继续遍历。代码:
class solution{
public:
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> result;
stack<TreeNode*> st;
st.push(root);
TreeNode* p = root->left;
while (st != null || p!=nullptr)
{
if (p != nullptr)
{
st.push(p);
p = p->left;
}
else
{
p = st.top();
st.pop();
result.push_back(p->val);
p = p->right;
}
}
}
return result;
}