二叉樹非遞歸遍歷

二叉樹有前序遍歷,中序遍歷,後序遍歷。大部分情況,我們都是用遞歸來寫這些遍歷,代碼簡潔明瞭。

如果能用非遞歸來寫這些遍歷,那麼會對這些遍歷理解得更深刻。

前序遍歷遞歸寫法:

private void displayPreOrder(Node root) {
		if (root != null) {
			System.out.print(" " + root.data);
			displayPreOrder(root.left);
			displayPreOrder(root.right);
		}
	}

前序遍歷得非遞歸寫法要根據遞歸運行步驟用棧來實現前序遍歷。前序遍歷就是在有孩子得情況下先遍歷自己再管孩子。每次遍歷完自己就從棧中pop出來,再把孩子push到棧裏。如此循環就能實現前序遍歷。

private void displayPreOrderNoRecursion(Node root) {
	    Stack<Node> s = new Stack<Node>();
	    Node cur;
	    if(root != null)
	        s.push(root);
	    while(!s.isEmpty()) {
	        cur = s.pop();
	        System.out.print(" " + cur.data);
	        if(cur.right != null) {
	        	s.push(cur.right);
	        }
	        if(cur.left != null) {
	        	s.push(cur.left);
	        }
	    }
	}

中序遍歷遞歸寫法:

private void displayInOrder(Node root) {
		if (root != null) {
			displayInOrder(root.left);
			System.out.print(" " + root.data);
			displayInOrder(root.right);
		}
	}

中序遍歷非遞歸寫法根據遞歸寫法步驟用棧來實現中序遍歷,因爲我們這裏是先遍歷左孩子再遍歷自己最後遍歷右孩子,所以我們先把二叉樹所有的左孩子從上到下push到棧中,然後每次遍歷從棧中pop出的節點並且檢測是否有右孩子,如果有右孩子就把右孩子push到棧中,然後繼續遍歷該節點的所有的左孩子從上到下push到棧中,如此循環就能實現中序遍歷。

private void displayInOrderNonRecursion(Node root) {
		Stack<Node> s = new Stack<Node>();
		Node current = root;
        while(current != null) {
        	s.push(current);
        	current = current.left;
        }
        
        while(!s.isEmpty()) {
        	current = s.pop();
        	System.out.print(" " + current.data);
        	if(current.right != null) {
        		current = current.right;
        		s.push(current);
        		while(current.left != null) {
            		current = current.left;
            		s.push(current);
            	}
        	}
        }
	}

接下來是後序遍歷,稍有些複雜。

後序遍歷遞歸寫法:

private void displayPostOrder(Node root) {
		if (root != null) {
			displayPostOrder(root.left);
			displayPostOrder(root.right);
			System.out.print(" " + root.data);
		}
	}

後序遍歷的非遞歸寫法就是按照遞歸寫法的步驟實現的。後序遍歷顧名思義就是先遍歷左孩子右孩子最後再遍歷自己。先將根結點push棧中,接下來在檢測棧是否爲空的循環條件下,檢測該檢查棧頂節點如果沒有孩子或者有孩子且孩子已經被遍歷的情況就將該節點pop出來遍歷,然後根據該節點查看是否有左孩子或者右孩子,如果有,就按照先查看右孩子再查看左孩子的順序將孩子push棧中。因爲我們是先遍歷左孩子再遍歷右孩子所以push入棧的順序應該是先push右孩子再push左孩子,這樣再pop的時候就是先取左孩子再取右孩子。這樣循環就能實現後序遍歷。

private void displayPostOrderNonRecursion(Node root) {
		Stack<Node> s = new Stack<Node>();
        if(root != null)
        	s.push(root);
        Node current = null;
        Node pre = null;
        
        while(!s.isEmpty()) {
        	current = s.peek();
        	if((current.left == null && current.right == null) ||
        			(pre != null && (pre == current.left || pre == current.right))) {
        		s.pop();
        		System.out.print(" " + current.data);
        		pre = current;
        	} else {
	        	if(current.right != null) {
	        		s.push(current.right);
	        	}
	        	if(current.left != null) {
	        		s.push(current.left);
	        	}
        	}
        }
	}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章