好久未更新博客了,翻出之前的一個算法集,作了些修改,發到這裏,以饗讀者。javascript
算法是關於二叉樹遍歷的內容。二叉樹遍歷傳統上通常有四種算法:一、遞歸前序遍歷,二、遞歸中序遍歷,三、遞歸後序遍歷,4、非遞歸層次遍歷(隊列輔助)。這四種算法都是大學教課書《數據結構》上的內容,前三種都很是簡單,最後一種略略複雜一點兒,這裏就不贅述了,只給出javascript的源程序。css
另外五種分別是:一、非遞歸前序遍歷(單棧輔助),二、非遞歸中序遍歷(單棧輔助),三、非遞歸後序遍歷(單棧輔助),四、非遞歸後序遍歷(雙棧輔助),五、遞歸層次遍歷。這五種算法中算法三、4不容易理解,可在Visual Studio中單步執行,並跟蹤棧的狀態。而算法5則很是精巧,層次遍歷通常多選用隊列輔助的算法,算法5的時間、空間效率並不比依靠隊列輔助的層次遍歷算法更低,但對學習遞歸思想很是有幫助,故此次翻出舊做時,一併加上了。html
算法使用javascript編寫,使用了javascript的自定義對象和爲已有對象添加自定義方法的功能。下面是完整的HTML文件(單文件),直接保存後就能夠運行了。 java
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Algorithm Of Traversing Binary Tree - 夢遼軟件</title>
- <style type="text/css">
- P{
- font-family:宋體;
- font-size:9pt;
- }
- </style>
- </head>
- <body>
- <p>二叉樹遍歷算法<br />
- 白宇 - 夢遼軟件工做室 - 博訊網絡有限責任公司<br />
- 2011.05.27<br />
- 2013.04.13(增長遞歸層次遍歷)</p>
- <p>二叉樹示意圖:</p>
- <pre> 1
- / \
- / \
- / \
- / \
- / \
- 2 3
- / \ \
- / \ \
- / \ \
- / \ \
- 4 5 6
- \ / / \
- \ / / \
- 7 8 9 10
- / / / \ \
- 11 12 13 14 15</pre>
- <script type="text/javascript">
- function BTNode(value){ //自定義對象的構造函數
- this.value=value;
- this.left=null;
- this.right=null;
- }
- //爲Array對象添加自定義方法
- Array.prototype.isEmpty=function(){return this.length==0;}; //用數組模擬棧或隊,判空方法
- //=============================================================
- function show(value){ //顯示二叉樹的節點
- document.write(value+" ");
- }
- function buildTree(){ //生成一顆如上圖所示的二叉樹
- var root=new BTNode(1);
- root.left=new BTNode(2);
- root.right=new BTNode(3);
- root.left.left=new BTNode(4);
- root.left.right=new BTNode(5);
- root.right.right=new BTNode(6);
- root.left.left.right=new BTNode(7);
- root.left.right.left=new BTNode(8);
- root.right.right.left=new BTNode(9);
- root.right.right.right=new BTNode(10);
- root.left.left.right.left=new BTNode(11);
- root.left.right.left.left=new BTNode(12);
- root.right.right.left.left=new BTNode(13);
- root.right.right.left.right=new BTNode(14);
- root.right.right.right.right=new BTNode(15);
- return root;
- }
- function preorder(root){ //遞歸前序遍歷
- if(root==null) return;
- show(root.value); //顯示根節點
- preorder(root.left); //前序遍歷左子樹
- preorder(root.right); //前序遍歷右子樹
- }
- function inorder(root){ //遞歸中序遍歷
- if(root==null) return;
- inorder(root.left);
- show(root.value);
- inorder(root.right);
- }
- function postorder(root){ //遞歸後序遍歷
- if(root==null) return;
- postorder(root.left);
- postorder(root.right);
- show(root.value);
- }
- function getDepth(root){ //遞歸層次遍歷 - 獲取二叉樹深度
- if(root==null) return 0;
- var leftDepth=getDepth(root.left);
- var rightDepth=getDepth(root.right);
- return Math.max(leftDepth, rightDepth)+1; //返回+1表示加當前層
- }
- function showNodeOfLevel(root, level){ //遞歸層次遍歷 - 遍歷某一層節點
- if(root==null||level<0) return;
- if(level==0) show(root.value);
- showNodeOfLevel(root.left, level-1);
- showNodeOfLevel(root.right, level-1);
- }
- function levelorder(root){ //遞歸層次遍歷
- var depth=getDepth(root);
- for(var i=0;i<depth;i++)
- showNodeOfLevel(root, i)
- }
- function iterativePreorder(root){ //非遞歸前序遍歷
- var stack=[]; //模擬棧
- stack.push(root);
- do{
- if((root=stack.pop())!=null){ //出棧
- show(root.value);
- stack.push(root.right); //右子節點入棧
- stack.push(root.left); //左子節點入棧
- }
- }while(!stack.isEmpty());
- }
- function iterativeInorder(root){ //非遞歸中序遍歷
- var stack=[];
- while(true){
- for(;root!=null;rootroot=root.left) //將當前節點左子樹的所有節點逐一入棧
- stack.push(root);
- if(stack.isEmpty()) break;
- root=stack.pop();
- show(root.value);
- rootroot=root.right; //遍歷右子樹
- }
- }
- function iterativeSingleStackPostorder(root){ //非遞歸後序遍歷(單棧)
- var stack=[],flag=root; //flag標識已經遍歷過的節點
- while(root!=null){ //逐一處理每一個節點的左右子樹
- for(;root.left!=null;rootroot=root.left)
- stack.push(root); //左子樹的節點逐一入棧
- while(root.right==null||root.right==flag){ //需判斷上次遍歷的節點是不是當前節點的右節點
- show(root.value);
- flag=root;
- if(stack.isEmpty()) return;
- root=stack.pop();
- }
- stack.push(root); //多是從新將該節點入棧
- rootroot=root.right; //轉向右子樹
- }
- }
- function iterativeDoubleStackPostorder(root){ //非遞歸後序遍歷(雙棧)
- var stack=[],result=[];
- if(root!=null) stack.push(root);
- while(!stack.isEmpty()){ //按照根左右順序逐一入棧、出棧、二次入棧
- result.push(root=stack.pop());
- if(root.left!=null) stack.push(root.left);
- if(root.right!=null) stack.push(root.right);
- }
- while(!result.isEmpty())
- show(result.pop().value);
- }
- function iterativeLevelorder(root){ //非遞歸層次遍歷
- var queue=[]; //模擬隊列
- queue.unshift(root); //插入根節點到隊列最前面
- do{
- if((root=queue.pop())!=null){ //從隊列最後面取節點
- show(root.value);
- queue.unshift(root.left); //左子節點入隊
- queue.unshift(root.right); //右子節點入隊
- }
- }while(!queue.isEmpty());
- }
- var root=buildTree();
- document.write("<p>遞歸前序遍歷:");
- preorder(root);
- document.write("</p><p>遞歸中序遍歷:");
- inorder(root);
- document.write("</p><p>遞歸後序遍歷:");
- postorder(root);
- document.write("</p><p>遞歸層次遍歷:");
- levelorder(root);
- document.write("</p><p>非遞歸前序遍歷(單棧):");
- iterativePreorder(root);
- document.write("</p><p>非遞歸中序遍歷(單棧):");
- iterativeInorder(root);
- document.write("</p><p>非遞歸後序遍歷(單棧):");
- iterativeSingleStackPostorder(root);
- document.write("</p><p>非遞歸後序遍歷(雙棧):");
- iterativeDoubleStackPostorder(root);
- document.write("</p><p>非遞歸層次遍歷(隊列):");
- iterativeLevelorder(root);
- document.write("</p>");
- </script>
- </body>
- </html>
運行截圖:算法