二叉树遍历(前中后层序/非递归)

一:前中后序递归实现
[cpp]  view plain copy
  1. /* 
  2. 前中后序的递归实现理解起来最为简单,要点在于visit(node)的位置。 
  3. */  
  4. /* 
  5. 前中后序递归实现 
  6. */  
  7. //前序遍历  
  8. void BT_PreOrder(BitTree node)  
  9. {  
  10.     if(!node) return;  
  11.   
  12.     visit(node);  
  13.     BT_PreOrder(node->left);  
  14.     BT_PreOrder(node->right);  
  15. }  
  16.   
  17. //中序遍历  
  18. void BT_InOrder(BitTree node)  
  19. {  
  20.     if(!node) return;  
  21.   
  22.     BT_PreOrder(node->left);  
  23.     visit(node);  
  24.     BT_PreOrder(node->right);  
  25. }  
  26.   
  27. //中序遍历  
  28. void BT_PostOrder(BitTree node)  
  29. {  
  30.     if(!node) return;  
  31.   
  32.     BT_PreOrder(node->left);  
  33.     BT_PreOrder(node->right);  
  34.     visit(node);  
  35. }  



二:层序递归实现
[cpp]  view plain copy
  1. /* 
  2. 层序遍历 
  3. 这种方式用队列来实现,也是最容易理解的方式,思路如下: 
  4. 按照层序遍历的定义,访问完当前节点之后,则当前节点的左子节点具备了倒数第二优先级,当前节点的右子节点具备了倒数第一优先级,利用队列先进先出的特性(可以确定最低的优先级),可以实现。 
  5. */  
  6. void BT_LevelOrder(BitTree node)  
  7. {  
  8.     if(!node) return;  
  9.   
  10.     queue<BitTree> q;  
  11.     q.push(node);  
  12.   
  13.     BitTree pvNode;  
  14.     while(!q.empty())  
  15.     {  
  16.         pvNode = q.pop();  
  17.         visit(pvNode);  
  18.   
  19.         if(!pvNode->left) q.push(pvNode->left);  
  20.         if(!pvNode->right) q.push(pvNode->right);  
  21.     }  
  22. }  




三:前序非递归实现
[cpp]  view plain copy
  1. /* 
  2. 前序遍历非递归实现1 
  3. 这种方式用栈来实现,也是最容易理解的方式,思路如下: 
  4. 按照前序遍历的定义,访问完当前节点之后,则当前节点的左子节点具备了第一优先级,当前节点的右子节点具备了第二优先级, 
  5. 利用栈后进先出的特性(可以确定最高的优先级),可以实现。 
  6. */  
  7. void BT_PreOrderNoRec(BitTree node)  
  8. {  
  9.     if(!node) return;  
  10.   
  11.     stack<BitTree> s;  
  12.     BitTree pvNode;  
  13.     s.push(node);  
  14.     while(!s.empty())  
  15.     {  
  16.         pvNode = s.pop();  
  17.         visit(pvNode);  
  18.   
  19.         if(!pvNode->right) s.push(pvNode->right);  
  20.         if(!pvNode->left)  s.push(pvNode->left);  
  21.     }  
  22. }  
  23.   
  24. /* 
  25. 前序遍历非递归实现2 
  26. 在网上看到的一种写法,个人觉得不如第一种实现起来更易懂 
  27. */  
  28. void BT_PreOrderNoRec2(BitTree node)  
  29. {  
  30.     if(!node) return;  
  31.   
  32.     stack<BitTree> s;  
  33.     while(!node && !s.empty())  
  34.     {  
  35.         /*如果当前节点不为空,则直接访问,然后将节点存储到栈中(仅仅用来将来寻找右子节点),然后当前节点变为左字节点*/  
  36.         if(node)  
  37.         {  
  38.             visit(node);  
  39.             s.push(node);  
  40.             node = node->left;  
  41.         }  
  42.         /*如果当前节点为空,则到栈中取出上一个节点,并找出右子节点进行访问*/  
  43.         else  
  44.         {  
  45.             node = s.pop();  
  46.             node = s.right;  
  47.         }  
  48.     }  
  49. }  



四:中序非递归

[cpp]  view plain copy
  1. /* 
  2. 中序遍历非递归实现 
  3. 用栈来实现,这种方式可以用递归的思路来理解 
  4. */  
  5. void BT_InOrderNoRec(BitTree node)  
  6. {  
  7.     if(!node) return;  
  8.   
  9.     stack<BitTree> s;  
  10.     while(!s.empty())  
  11.     {  
  12.         /*如果当前节点不为空,则不访问,而是将它放入栈中,然后当前节点变为左字节点; 
  13.           一直采取这种方式,根据栈先进后出的特点,将来访问的时候左字节点在前,当前节点在后; 
  14.           正好是中序遍历的特性 
  15.         */  
  16.         if(!node)  
  17.         {  
  18.             push(node);  
  19.             node = node->left();  
  20.         }  
  21.         /*如果当前节点为空,则去栈里取出节点访问,然后访问右子节点。 
  22.           这里有些不好理解,其实这里的开端是左字节点为空了,所以访问了当前节点,然后右子节点; 
  23.           同时当前节点为根的二叉树其实是上层的左字节点,依次类推正好是中序遍历的特性 
  24.         */  
  25.         else  
  26.         {  
  27.             node = s.pop();  
  28.             visit(node);  
  29.             node = node->right;  
  30.         }  
  31.     }  
  32. }  



五:后序非递归

[cpp]  view plain copy
  1. /* 
  2. 后序遍历非递归实现 
  3. 用栈来实现,不是很好理解,但是起码不用借助各种标志位 
  4. 思路如注释所写 
  5. */  
  6. void BT_PostOrderNoRec(BitTree node)  
  7. {  
  8.     if(!node) return;  
  9.   
  10.     stack<BitTree> s;  
  11.     BitTree tmp;//用来标志刚刚访问过的节点  
  12.     while(!node && !s.empty())  
  13.     {  
  14.         //如果当前节点不为空,则压入栈,当前节点变为左字节点  
  15.         if(node)  
  16.         {  
  17.             s.push(node);  
  18.             node = node->left;  
  19.         }  
  20.         //如果为空,则需要根据栈顶的节点来判定下一步  
  21.         else  
  22.         {  
  23.             //获取栈顶节点,不是pop  
  24.             node = s.getPop();  
  25.             //如果栈顶节点有右子节点,并且(这不好理解,但很重要)右子节点不是我们刚刚访问过的,  
  26.             //则,我们要去右子树访问  
  27.             if(node->right && node->right != tmp)  
  28.             {  
  29.                 //把右子树当作一个新的开始进行访问:根节点压入栈,访问左字节点  
  30.                 s.push(node->right);  
  31.                 node = node->right->left;  
  32.             }  
  33.             //如果栈顶节点没有右子节点,或者我们刚刚访问过右子节点,则达到后序遍历的要求,我们可以访问当前节点  
  34.             else  
  35.             {  
  36.                 //访问当前节点,设置标志节点(tmp)为当前节点,当前节点置为空  
  37.                 node = s.pop();  
  38.                 visit(node);  
  39.                 tmp = node;  
  40.                 node = null;  
  41.             }  
  42.         }  
  43.     }  
  44. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值