二叉樹結點數據結構
public class TreeNode{
public int key = 0;
public String data = null;
public boolean isVisited = false;
public TreeNode leftChild = null;
public TreeNode rightChild = null;
public TreeNode(int key,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
初始化根節點
TreeNode root = null;
public javatest(){
root = new TreeNode(1,"root A");
}
創建二叉樹
public void createBinTree(TreeNode root){
TreeNode newNodeB = new TreeNode(2,"B");
TreeNode newNodeC = new TreeNode(3,"C");
TreeNode newNodeD = new TreeNode(4,"D");
TreeNode newNodeE = new TreeNode(5,"E");
TreeNode newNodeF = new TreeNode(6,"F");
root.leftChild = newNodeB;
root.rightChild = newNodeC;
root.leftChild.leftChild = newNodeD;
root.leftChild.rightChild = newNodeE;
root.rightChild.rightChild = newNodeF;
}
訪問節點
public void visted(TreeNode subTree) {
subTree.isVisited = true;
System.out.println("key:" + subTree.key + "--name:" + subTree.data);
}
遞歸與非遞歸進行前中後序遍歷
前序遍歷
// 前序遍歷
public void preOrder(TreeNode subTree) {
if (subTree != null) {
visted(subTree);
preOrder(subTree.leftChild);
preOrder(subTree.rightChild);
}
}
非遞歸藉助棧來實現
1.定義node來遍歷二叉樹,定義棧來儲存二叉樹結點
2.利用while循環,一開始node指向根節點,訪問node,併入棧,將node更新爲左子樹,繼續循環;當node爲null時循環停止,此時node代表的是最左節點的左節點,爲null時表示最左節點和其左子樹打印完畢。
3.接下來需要打印左節點的右子樹,取出棧頂元素,並將node更新爲棧頂元素的右子樹。
// 前序遍歷的非遞歸實現
public void nonRecPreOrder(TreeNode root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = root;
while (node != null || stack.size() > 0) {
while (node != null) {
visted(node);
stack.push(node);
node = node.leftChild;
}
while (stack.size() > 0) {
node = stack.pop();
node = node.rightChild;
}
}
}
中序遍歷
// 中序遍歷
public void inOrder(TreeNode subTree) {
if (subTree != null) {
inOrder(subTree.leftChild);
visted(subTree);
inOrder(subTree.rightChild);
}
}
非遞歸過程
1.定義node來遍歷二叉樹,定義棧來儲存二叉樹結點
2.利用while循環,一開始node指向根節點,入棧,然後將node更新爲左子樹,繼續循環;直到node爲null時第二層while循環停止,此時node代表最左節點的左節點。
3.接下來需要打印最左節點的左子樹;因爲左字樹爲空,所以直接打印他的根,取出棧頂元素,這就是最後一顆樹的根,打印,刪除棧頂結點,將node更新爲棧頂元素的右結點;
// 中序遍歷的非遞歸實現
public void nonRecInOrder(TreeNode root) {
Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
TreeNode node = root;
while (node != null || stack.size() > 0) {
// 存在左子樹
while (node != null) {
stack.push(node);
node = node.leftChild;
}
// 棧非空
if (stack.size() > 0) {
node = stack.pop();
visted(node);
node = node.rightChild;
}
}
}
後序遍歷
// 後續遍歷
public void postOrder(TreeNode subTree) {
if (subTree != null) {
postOrder(subTree.leftChild);
postOrder(subTree.rightChild);
visted(subTree);
}
}
非遞歸過程
1.循環將左子樹左節點全部入棧
2.入棧結束,當前root爲最左節點的左節點;當前節點無右子樹或右子樹已經輸出,則訪問當前節點後用node記錄剛訪問過的節點,root = stack.pop();更新root爲棧內下一元素。
3.當前root有右子樹時,右子樹入棧,當前節點更新爲節點的右子樹。
// 後序遍歷的非遞歸實現
public void noRecPostOrder(TreeNode root) {
Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
TreeNode node = root;
while (root!= null) {
// 左子樹入棧
for (; root.leftChild != null; root = root.leftChild) {
stack.push(root);
}
// 當前結點無右子樹或右子樹已經輸出
while (root != null && (root.rightChild == null || root.rightChild == node)) {
visted(root);
// 紀錄上一個已輸出結點
node = root;
if (stack.empty())
return;
root = stack.pop();
}
// 處理右子樹
stack.push(root);
root = root.rightChild;
}
}
完整測試
import java.util.Stack;
public class javatest {
TreeNode root = null;
public class TreeNode{
public int key = 0;
public String data = null;
public boolean isVisited = false;
public TreeNode leftChild = null;
public TreeNode rightChild = null;
public TreeNode(int key,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
public javatest(){
root = new TreeNode(1,"root A");
}
public void createBinTree(TreeNode root){
TreeNode newNodeB = new TreeNode(2,"B");
TreeNode newNodeC = new TreeNode(3,"C");
TreeNode newNodeD = new TreeNode(4,"D");
TreeNode newNodeE = new TreeNode(5,"E");
TreeNode newNodeF = new TreeNode(6,"F");
root.leftChild = newNodeB;
root.rightChild = newNodeC;
root.leftChild.leftChild = newNodeD;
root.leftChild.rightChild = newNodeE;
root.rightChild.rightChild = newNodeF;
}
// 前序遍歷
public void preOrder(TreeNode subTree) {
if (subTree != null) {
visted(subTree);
preOrder(subTree.leftChild);
preOrder(subTree.rightChild);
}
}
// 中序遍歷
public void inOrder(TreeNode subTree) {
if (subTree != null) {
inOrder(subTree.leftChild);
visted(subTree);
inOrder(subTree.rightChild);
}
}
// 後續遍歷
public void postOrder(TreeNode subTree) {
if (subTree != null) {
postOrder(subTree.leftChild);
postOrder(subTree.rightChild);
visted(subTree);
}
}
// 前序遍歷的非遞歸實現
public void nonRecPreOrder(TreeNode p) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = p;
while (node != null || stack.size() > 0) {
while (node != null) {
visted(node);
stack.push(node);
node = node.leftChild;
}
while (stack.size() > 0) {
node = stack.pop();
node = node.rightChild;
}
}
}
// 中序遍歷的非遞歸實現
public void nonRecInOrder(TreeNode p) {
Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
TreeNode node = p;
while (node != null || stack.size() > 0) {
// 存在左子樹
while (node != null) {
stack.push(node);
node = node.leftChild;
}
// 棧非空
if (stack.size() > 0) {
node = stack.pop();
visted(node);
node = node.rightChild;
}
}
}
// 後序遍歷的非遞歸實現
public void noRecPostOrder(TreeNode root) {
Stack<TreeNode> stack = new Stack<javatest.TreeNode>();
TreeNode node = root;
while (root!= null) {
// 左子樹入棧
for (; root.leftChild != null; root = root.leftChild) {
stack.push(root);
}
// 當前結點無右子樹或右子樹已經輸出
while (root != null && (root.rightChild == null || root.rightChild == node)) {
visted(root);
// 紀錄上一個已輸出結點
node = root;
if (stack.empty())
return;
root = stack.pop();
}
// 處理右子樹
stack.push(root);
root = root.rightChild;
}
}
public void visted(TreeNode subTree) {
subTree.isVisited = true;
System.out.println("key:" + subTree.key + "--name:" + subTree.data);
}
// 測試
public static void main(String[] args) {
javatest bt = new javatest();
bt.createBinTree(bt.root);
System.out.println("*******(前序遍歷)[ABDECF]遍歷*****************");
bt.preOrder(bt.root);
System.out.println("*******(中序遍歷)[DBEACF]遍歷*****************");
bt.inOrder(bt.root);
System.out.println("*******(後序遍歷)[DEBFCA]遍歷*****************");
bt.postOrder(bt.root);
System.out.println("***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************");
bt.nonRecPreOrder(bt.root);
System.out.println("***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************");
bt.nonRecInOrder(bt.root);
System.out.println("***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************");
bt.noRecPostOrder(bt.root);
}
}
結果:
*******(前序遍歷)[ABDECF]遍歷*****************
key:1--name:root A
key:2--name:B
key:4--name:D
key:5--name:E
key:3--name:C
key:6--name:F
*******(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:root A
key:3--name:C
key:6--name:F
*******(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:root A
***非遞歸實現****(前序遍歷)[ABDECF]遍歷*****************
key:1--name:root A
key:2--name:B
key:4--name:D
key:3--name:C
key:6--name:F
***非遞歸實現****(中序遍歷)[DBEACF]遍歷*****************
key:4--name:D
key:2--name:B
key:5--name:E
key:1--name:root A
key:3--name:C
key:6--name:F
***非遞歸實現****(後序遍歷)[DEBFCA]遍歷*****************
key:4--name:D
key:5--name:E
key:2--name:B
key:6--name:F
key:3--name:C
key:1--name:root A