遍历二叉树的九种算法

简介:

很久未更新博客了,翻出以前的一个算法集,做了些修改,发到这里,以飨读者。

  算法是关于二叉树遍历的内容。二叉树遍历传统上一般有四种算法:1、递归前序遍历,2、递归中序遍历,3、递归后序遍历,4、非递归层次遍历(队列辅助)。这四种算法都是大学教课书《数据结构》上的内容,前三种都非常简单,最后一种略略复杂一点儿,这里就不赘述了,只给出javascript的源程序。

  另外五种分别是:1、非递归前序遍历(单栈辅助),2、非递归中序遍历(单栈辅助),3、非递归后序遍历(单栈辅助),4、非递归后序遍历(双栈辅助),5、递归层次遍历。这五种算法中算法3、4不容易理解,可在Visual Studio中单步执行,并跟踪栈的状态。而算法5则非常精巧,层次遍历一般多选用队列辅助的算法,算法5的时间、空间效率并不比依靠队列辅助的层次遍历算法更低,但对学习递归思想非常有帮助,故这次翻出旧作时,一并加上了。

  算法使用javascript编写,使用了javascript的自定义对象和为已有对象添加自定义方法的功能。下面是完整的HTML文件(单文件),直接保存后就可以运行了。 

 
 
  1. <html xmlns="http://www.w3.org/1999/xhtml"> 
  2. <head> 
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
  4. <title>Algorithm Of Traversing Binary Tree - 梦辽软件</title> 
  5. <style type="text/css"> 
  6. P{  
  7.     font-family:宋体;  
  8.     font-size:9pt;  
  9. }  
  10. </style> 
  11. </head> 
  12. <body> 
  13. <p>二叉树遍历算法<br /> 
  14. 白宇 - 梦辽软件工作室 - 博讯网络有限责任公司<br /> 
  15. 2011.05.27<br /> 
  16. 2013.04.13(增加递归层次遍历)</p> 
  17. <p>二叉树示意图:</p> 
  18. <pre>           1  
  19.           / \  
  20.          /   \  
  21.         /     \  
  22.        /       \  
  23.       /         \  
  24.      2           3  
  25.     / \           \  
  26.    /   \           \  
  27.   /     \           \  
  28.  /       \           \  
  29. 4         5           6  
  30.  \       /           / \  
  31.   \     /           /   \  
  32.    7   8           9     10  
  33.   /   /           / \     \  
  34. 11  12          13   14    15</pre> 
  35. <script type="text/javascript"> 
  36. function BTNode(value){ //自定义对象的构造函数  
  37.     this.value=value;  
  38.     this.left=null;  
  39.     this.right=null;  
  40. }  
  41. //为Array对象添加自定义方法  
  42. Array.prototype.isEmpty=function(){return this.length==0;}; //用数组模拟栈或队,判空方法  
  43.  
  44. //=============================================================  
  45.  
  46. function show(value){ //显示二叉树的节点  
  47.     document.write(value+" ");  
  48. }  
  49. function buildTree(){ //生成一颗如上图所示的二叉树  
  50.     var root=new BTNode(1);  
  51.     root.left=new BTNode(2);  
  52.     root.right=new BTNode(3);  
  53.     root.left.left=new BTNode(4);  
  54.     root.left.right=new BTNode(5);  
  55.     root.right.right=new BTNode(6);  
  56.     root.left.left.right=new BTNode(7);  
  57.     root.left.right.left=new BTNode(8);  
  58.     root.right.right.left=new BTNode(9);  
  59.     root.right.right.right=new BTNode(10);  
  60.     root.left.left.right.left=new BTNode(11);  
  61.     root.left.right.left.left=new BTNode(12);  
  62.     root.right.right.left.left=new BTNode(13);  
  63.     root.right.right.left.right=new BTNode(14);  
  64.     root.right.right.right.right=new BTNode(15);  
  65.     return root;  
  66. }  
  67. function preorder(root){ //递归前序遍历  
  68.     if(root==null) return;  
  69.     show(root.value); //显示根节点  
  70.     preorder(root.left); //前序遍历左子树  
  71.     preorder(root.right); //前序遍历右子树  
  72. }  
  73. function inorder(root){ //递归中序遍历  
  74.     if(root==null) return;  
  75.     inorder(root.left);  
  76.     show(root.value);  
  77.     inorder(root.right);  
  78. }  
  79. function postorder(root){ //递归后序遍历  
  80.     if(root==null) return;  
  81.     postorder(root.left);  
  82.     postorder(root.right);  
  83.     show(root.value);  
  84. }  
  85. function getDepth(root){ //递归层次遍历 - 获取二叉树深度  
  86.     if(root==null) return 0;  
  87.     var leftDepth=getDepth(root.left);  
  88.     var rightDepth=getDepth(root.right);  
  89.     return Math.max(leftDepth, rightDepth)+1; //返回+1表示加当前层  
  90. }  
  91. function showNodeOfLevel(root, level){ //递归层次遍历 - 遍历某一层节点  
  92.     if(root==null||level<0) return;  
  93.     if(level==0) show(root.value);  
  94.     showNodeOfLevel(root.left, level-1);  
  95.     showNodeOfLevel(root.right, level-1);  
  96. }  
  97. function levelorder(root){ //递归层次遍历  
  98.     var depth=getDepth(root);  
  99.     for(var i=0;i<depth;i++)  
  100.         showNodeOfLevel(root, i)  
  101. }  
  102. function iterativePreorder(root){ //非递归前序遍历  
  103.     var stack=[]; //模拟栈  
  104.     stack.push(root);  
  105.     do{  
  106.         if((root=stack.pop())!=null){ //出栈  
  107.             show(root.value);  
  108.             stack.push(root.right); //右子节点入栈  
  109.             stack.push(root.left); //左子节点入栈  
  110.         }  
  111.     }while(!stack.isEmpty());  
  112. }  
  113. function iterativeInorder(root){ //非递归中序遍历  
  114.     var stack=[];  
  115.     while(true){  
  116.         for(;root!=null;rootroot=root.left) //将当前节点左子树的全部节点逐一入栈  
  117.             stack.push(root);  
  118.         if(stack.isEmpty()) break;  
  119.         root=stack.pop();  
  120.         show(root.value);  
  121.         rootroot=root.right; //遍历右子树  
  122.     }  
  123. }  
  124. function iterativeSingleStackPostorder(root){ //非递归后序遍历(单栈)  
  125.     var stack=[],flag=root; //flag标识已经遍历过的节点  
  126.     while(root!=null){ //逐一处理每个节点的左右子树  
  127.         for(;root.left!=null;rootroot=root.left)  
  128.             stack.push(root); //左子树的节点逐一入栈  
  129.         while(root.right==null||root.right==flag){ //需判断上次遍历的节点是否是当前节点的右节点  
  130.             show(root.value);  
  131.             flag=root;  
  132.             if(stack.isEmpty()) return;  
  133.             root=stack.pop();  
  134.         }  
  135.         stack.push(root); //可能是重新将该节点入栈  
  136.         rootroot=root.right; //转向右子树  
  137.     }  
  138. }  
  139. function iterativeDoubleStackPostorder(root){ //非递归后序遍历(双栈)  
  140.     var stack=[],result=[];  
  141.     if(root!=null) stack.push(root);  
  142.     while(!stack.isEmpty()){ //按照根左右顺序逐一入栈、出栈、二次入栈  
  143.         result.push(root=stack.pop());  
  144.         if(root.left!=null) stack.push(root.left);  
  145.         if(root.right!=null) stack.push(root.right);  
  146.     }  
  147.     while(!result.isEmpty())  
  148.         show(result.pop().value);  
  149. }  
  150. function iterativeLevelorder(root){ //非递归层次遍历  
  151.     var queue=[]; //模拟队列  
  152.     queue.unshift(root); //插入根节点到队列最前面  
  153.     do{  
  154.         if((root=queue.pop())!=null){ //从队列最后面取节点  
  155.             show(root.value);  
  156.             queue.unshift(root.left); //左子节点入队  
  157.             queue.unshift(root.right); //右子节点入队  
  158.         }  
  159.     }while(!queue.isEmpty());  
  160. }  
  161.  
  162. var root=buildTree();  
  163. document.write("<p>递归前序遍历:");  
  164. preorder(root);  
  165. document.write("</p><p>递归中序遍历:");  
  166. inorder(root);  
  167. document.write("</p><p>递归后序遍历:");  
  168. postorder(root);  
  169. document.write("</p><p>递归层次遍历:");  
  170. levelorder(root);  
  171. document.write("</p><p>非递归前序遍历(单栈):");  
  172. iterativePreorder(root);  
  173. document.write("</p><p>非递归中序遍历(单栈):");  
  174. iterativeInorder(root);  
  175. document.write("</p><p>非递归后序遍历(单栈):");  
  176. iterativeSingleStackPostorder(root);  
  177. document.write("</p><p>非递归后序遍历(双栈):");  
  178. iterativeDoubleStackPostorder(root);  
  179. document.write("</p><p>非递归层次遍历(队列):");  
  180. iterativeLevelorder(root);  
  181. document.write("</p>");  
  182. </script> 
  183. </body> 
  184. </html> 

运行截图:










本文转自 BlackAlpha 51CTO博客,原文链接:http://blog.51cto.com/mengliao/1178079,如需转载请自行联系原作者
目录
相关文章
|
21小时前
|
存储 算法
【数据结构与算法】二叉树基础OJ--下(巩固提高)
【数据结构与算法】二叉树基础OJ--下(巩固提高)
|
21小时前
|
算法 Java
算法:Java计算二叉树从根节点到叶子结点的最大路径和
算法:Java计算二叉树从根节点到叶子结点的最大路径和
|
21小时前
|
算法
【算法与数据结构】二叉树(前中后)序遍历1
【算法与数据结构】二叉树(前中后)序遍历
|
21小时前
|
算法
【算法与数据结构】二叉树(前中后)序遍历2
【算法与数据结构】二叉树(前中后)序遍历
|
21小时前
|
算法
算法系列--递归(2)--二叉树专题(上)
算法系列--递归(2)--二叉树专题
24 0
|
21小时前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
21小时前
|
算法
算法系列--递归(2)--二叉树专题(下)
算法系列--递归(2)--二叉树专题(下)
20 0
|
21小时前
|
算法 索引
【算法与数据结构】深入二叉树实现超详解(全源码优化)
【算法与数据结构】深入二叉树实现超详解(全源码优化)
|
21小时前
|
存储 算法
【算法与数据结构】深入解析二叉树(二)之堆结构实现
【算法与数据结构】深入解析二叉树(二)之堆结构实现
|
21小时前
|
存储 算法 Python
数据结构与算法——二叉树介绍(附代码)
数据结构与算法——二叉树介绍(附代码)
22 3

热门文章

最新文章