二叉樹的遍歷


二叉樹的遍歷應該說是非常常見的,用遞歸的話程序非常簡單明了,而有的時候需要寫非遞歸的遍歷程序,這個時候就需要對此有一定的了解。

二叉樹的遍歷根據根節點和左右子節點遍歷順序的不同,可以分為三種:前序遍歷,中序遍歷,后序遍歷。前序遍歷就是先根節點->左節點->右節點。非遞歸前序遍歷編寫最簡單,最難的是后續遍歷。下面就來一一寫出它們的程序,這里用的是Java。非遞歸遍歷是一種DFS(深度優先搜素),從根節點開始一直遍歷到葉子節點,然后在從根節點往另一個路徑繼續遍歷。這里用到的數據結構是棧。Java里面用的是Stack類,它是數組實現,也可以用鏈表LinkedList來做棧。其實遞歸遍歷也用到了棧,只不過是系統棧,沒有顯示的輸出。

Node節點的定義:

public  class Node<T>
{
private T element;
private Node<T> left;
private Node<T> right;
public Node(T element,Node<T> left,Node<T> right)
{
this.element=element;
this.left=left;
this.right=right;
}
}


遞歸二叉樹遍歷:

//前序遍歷
public void printTree(Node<T> node)
{
if(node!=null)
{
System.out.print(node.element+" ");
printTree(node.left);
printTree(node.right);

}
}
//中序遍歷
public void printTree(Node<T> node)
{
if(node!=null)
{
printTree(node.left);
System.out.print(node.element+" ");
printTree(node.right);
}
}
//后續遍歷
public void printTree(Node<T> node)
{
if(node!=null)
{
printTree(node.left);
printTree(node.right);
System.out.print(node.element+" ");
}
}


非遞歸二叉樹遍歷:

//前序遍歷 非遞歸實現 三種遍歷中最簡單的
public void preTrave(Node<T> root)
{
if(root==null)
return;
Stack<Node> st=new Stack<Node>();
st.push(root);
while(!st.isEmpty())
{
Node<T> n=st.pop();
System.out.print(n.element+" ");
if(n.right!=null)
st.push(n.right); //先入棧右節點,再入棧左節點
if(n.left!=null)
st.push(n.left);
}
}

//中序遍歷 非遞歸實現 三種遍歷中的
public void midTrave(Node<T> root)
{
if(root==null)
return;
Stack<Node> st=new Stack<Node>();
Node<T> no=root;
while(no!=null || !st.isEmpty())
{
while(no!=null)
{
st.push(no); //不停地插入左節點
no=no.left;
}
if(!st.isEmpty())
{
Node<T> n=st.pop();
System.out.print(n.element+" ");
no=n.right; //獲取出棧節點的右節點
}
}
}

//后序遍歷 非遞歸實現 三種遍歷中是最難的,需要每個節點保存一個變量代表是否被讀取過
public void postTrave(Node<T> root)
{
if(root==null)
return;
Map.Entry<Node,Boolean> me;//這里用到Map內部類,類似於C++的pair函數,否則要自己重寫個類
Stack<Map.Entry<Node,Boolean>> st=new Stack<Map.Entry<Node,Boolean>>();
Node<T> no=root;
while(no!=null || !st.isEmpty())
{
while(no!=null)
{
me=new AbstractMap.SimpleEntry(no,false);
st.push(me); //不停地插入左節點
no=no.left;
}
if(!st.isEmpty())
{

Map.Entry<Node,Boolean> n=st.pop();
if(n.getValue()==false)
{
st.push(n);
n.setValue(true); //代表讀過該節點一次
no=n.getKey().right;
}
else //代表出棧的節點右節點已經讀取
{
System.out.print(n.getKey().element+" ");
no=null;
}
}
}
}


除了上面的三種遍歷,二叉樹還可以分層遍歷。這就是BFS(廣度優先搜索),先第一層,再第二層,以此類推。BFS用到的數據結構是隊列,先入先出。程序如下,它和前序遍歷類似,只不過把棧改成了隊列,然后左右節點進入的順序掉了一下。

程序如下:

//按層遍歷 就是將前序遍歷的棧改用為隊列,左右節點入隊順序改變一下
public void cengTrave(Node<T> root)
{
if(root==null)
return;
ArrayDeque<Node> st=new ArrayDeque<Node>();
st.offer(root);
while(!st.isEmpty())
{
Node<T> n=st.pop();
System.out.print(n.element+" ");
if(n.left!=null)
st.offer(n.left); //先左節點入隊列,再右節點
if(n.right!=null)
st.offer(n.right);
}
}




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷 二叉樹的遍歷
 
粤ICP备14056181号  © 2014-2021 ITdaan.com