二叉树的遍历(递归和非递归的实现)

一.二叉树的遍历(先序,中序,后序)的递归实现

实现二叉树的递归其实很简单,只要理解了二叉树的递归系统压栈是怎么压的,所谓的先序,中序,后序遍历的区别其实就是打印的时机的问腿而已了。

系统会把每一个节点压栈三次,打印第一次就是先序遍历,打印第二次就是中序遍历,打印第三次就是后序遍历。

下面上代码:

void proder(TreeNode* root)
{
if(root==nullptr) return ;
cout<<root->val<<" ";
if(root->left!=nullptr) proder(root->left);
if(root->right!=nullptr) proder(root->right);
}

这就是先序遍历,如果把cout语句放在proder(root->left)的后面,就是中序遍历。 如果把cout语句放在proder(root->right)后面,就是后序遍历。

二.二叉树的先序,中序,后序,层序的非递归实现

先序的非递归实现:

既然不能手动压栈,那我们就自己做一个栈,先序遍历是根左右,我们先把根结点压进栈,然后先压右孩子,再压左孩子,每次只弹出一个元素,弹出值作为当前节点,当无栈可压时,就一个一个弹,直到弹空为止:

下面上代码:

void PreOrder(TreeNode* root)
{
if(root==nullptr) return ;
stack<TreeNode*> sta;
sta.push(root);
while(!sta.empty())
{
cout<<sta.top->val<<" "<<;
root=sta.top();
sta.pop();
if(root->right!=nullptr) sta.push(root->right);
if(root->left!=nullptr) sta.push(root->left);
}
}

 中序的非递归实现:

中序遍历是左根右,这个跟先序遍历的非递归很不一样,首先,从根节点开始判断,如果不为空,压入当前节点,然后指向当前节点的左孩子,如果为空,节点指向栈顶,栈顶弹出,当前节点指向右孩子,直到栈空结束。

下面上代码:

void InOrder(TreeNode* root)
{
if(root==nullptr) return ;
stack<TreeNode*> sta;
while(root!=nullptr||!sta.empty())
{
if(root!=nullptr)
{
sta.push(root);
root=root->left;
}
else{
root=sta.top();
sta.pop();
root=root->right;
}
}
}

 后序遍历的非递归实现:

后序遍历是左右根,首先我们先看看先序遍历是根左右,操作是先压右再压左,我们就可以小小的调整一波,先压左再压右,就是根右左,然后我们再用一个栈把弹出来的元素再全部压进去,再弹出来就是左右根了,

下面上代码:
 

void PosOrder(TreeNode* root)
{
if(root==nullptr) return ;
stack<TreeNode*> sta1;
stack<TreeNode*> sta2;
sta1.push(root);
while(!sta1.empty())
{
root=sta1.top();
sta2.push(sta1.pop());
sta1.pop();
if(root->left!=nullptr) sta1.push(root->left);
if(root->right!=nullptr) sta2.push(root->right);
}
}
while(!sta2.empty())
{
cout<<sta2.top()<<" ";
sta2.pop();
}
}

二叉树的层序遍历的非递归实现:

层序遍历就是一层一层的遍历嘛,层序遍历不能用栈啦,广度优先遍历是用队列,深度优先遍历用栈,关于如何一层一层的打印,这个很简单,记录·好上一层的队列的长度就可以了。

下面上代码:

void Order(TreeNode* root)
{
if(root==nullptr) return ;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size=que.size();
while(size--)
{
cout<<que.top->val<<" ";
root=que.top();
if(root->left!=nullptr) que.push(root->left);
if(root->right!=nullptr) que.push(root->right);
}
}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值