版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/qq_33275597/article/details/52759223
一、二叉樹的定義:
二叉樹是樹形結構的一個重要類型。許多實際問題抽象出來的數據結構往往是二叉樹的形式,即使是一般的樹也能簡單地轉換為二叉樹,而且二叉樹的存儲結構及其算法都較為簡單,因此二叉樹顯得特別重要。
二叉樹(BinaryTree)是n(n≥0)個結點的有限集,它或者是空集(n=0),或者由一個根結點及兩棵互不相交的、分別稱作這個根的左子樹和右子樹的二叉樹組成。
這個定義是遞歸的。由於左、右子樹也是二叉樹, 因此子樹也可為空樹。下圖中展現了五種不同基本形態的二叉樹。
其中 (a) 為空樹, (b) 為僅有一個結點的二叉樹, (c) 是僅有左子樹而右子樹為空的二叉樹, (d) 是僅有右子樹而左子樹為空的二叉樹, (e) 是左、右子樹均非空的二叉樹。這里應特別注意的是,二叉樹的左子樹和右子樹是嚴格區分並且不能隨意顛倒的,圖 (c) 與圖 (d) 就是兩棵不同的二叉樹。
二、二叉樹的遍歷:
對於二叉樹來講最主要、最基本的運算是遍歷。
遍歷二叉樹 是指以一定的次序訪問二叉樹中的每個結點。所謂 訪問結點 是指對結點進行各種操作的簡稱。例如,查詢結點數據域的內容,或輸出它的值,或找出結點位置,或是執行對結點的其他操作。遍歷二叉樹的過程實質是把二叉樹的結點進行線性排列的過程。假設遍歷二叉樹時訪問結點的操作就是輸出結點數據域的值,那么遍歷的結果得到一個線性序列。
常見的遍歷方法:
1、先序遍歷法:先訪問根節點,再遍歷左子樹,最后遍歷右子樹;
2、中序遍歷法:先遍歷左子樹,再訪問根節點,最后遍歷右子樹;
3、后序遍歷法:先遍歷左子樹,再遍歷右子樹,最后訪問根節點。
三、話不多說,上代碼。
public class BinaryTree {
/**
* BinaryTree 的節點數據結構
*/
private class TreeNode{
private int key = 0;
private String data = null;
private boolean isVisited = false;
private TreeNode leftChild = null;
private TreeNode rightChild = null;
public TreeNode(){}
public TreeNode(int key,String data){
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
}
//獲取根節點
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
//定義根節點
private TreeNode root = null;
public BinaryTree(){
root = new TreeNode(1,"A");
}
/**
* 創建一棵二叉樹
*/
public void createBinaryTree(TreeNode root){
TreeNode nodeB = new TreeNode(2,"B");
TreeNode nodeC = new TreeNode(3,"C");
TreeNode nodeD = new TreeNode(4,"D");
TreeNode nodeE = new TreeNode(5,"E");
TreeNode nodeF = new TreeNode(6,"F");
root.leftChild = nodeB;
root.rightChild = nodeC;
nodeB.leftChild = nodeD;
nodeB.rightChild = nodeE;
nodeC.rightChild = nodeF;
}
/**
* 前序遍歷
*/
public void preOrder(TreeNode node){
if(node != null){
visited(node);
preOrder(node.leftChild);
preOrder(node.rightChild);
}
}
/**
* 中序遍歷
* @param node
*/
public void inOrder(TreeNode node){
if(node != null){
preOrder(node.leftChild);
visited(node);
preOrder(node.rightChild);
}
}
/**
* 后序遍歷
* @param node
*/
public void postOrder(TreeNode node){
if(node != null){
preOrder(node.leftChild);
preOrder(node.rightChild);
visited(node);
}
}
/**
* 非遞歸前序遍歷
* @param node
*/
public void nonRecPreOrder(TreeNode node){
Stack<TreeNode> stack = new Stack<>();
TreeNode pNode = node;
while(pNode != null || stack.size()>0){
while(pNode != null){
visited(pNode);
stack.push(pNode);
pNode = pNode.leftChild;
}
if(stack.size()>0){
pNode = stack.pop();
pNode = pNode.rightChild;
}
}
}
/**
* 非遞歸中序遍歷
* @param node
*/
public void nonRecInOrder(TreeNode node){
Stack<TreeNode> stack = new Stack<>();
TreeNode pNode = node;
while(pNode != null || stack.size()>0){
while(pNode != null){
stack.push(pNode);
pNode = pNode.leftChild;
}
if(stack.size()>0){
pNode = stack.pop();
visited(pNode);
pNode = pNode.rightChild;
}
}
}
/**
* 非遞歸后序遍歷
* @param pNode
*/
public void nonRecPostOrder(TreeNode pNode){
Stack<TreeNode> stack = new Stack<>();
TreeNode node = pNode;
while(pNode != null){
//左子樹入棧
while(pNode.leftChild != null){
stack.push(pNode);
pNode = pNode.leftChild;
}
//當前節點無右子樹或者右子樹已輸出
while(pNode != null && (pNode.rightChild == null || pNode.rightChild == node)){
visited(pNode);
//記錄上一個已輸出的節點
node = pNode;
if(!stack.isEmpty()){
pNode = stack.pop();
}else{
return;
}
}
//右子樹入棧
stack.push(pNode);
pNode = pNode.rightChild;
}
}
private void visited(TreeNode node) {
node.isVisited = true;
System.out.println(node.data+","+node.key);
}
/**
* 計算樹的高度
*/
private int height(TreeNode node){
if(node == null){
return 0;
}else{
int i = height(node.leftChild);
int j = height(node.rightChild);
return (i<j)?j+1:i+1;
}
}
/**
* 計算樹的節點數
* @param node
* @return 樹的節點數
*/
private int size(TreeNode node){
if(node == null){
return 0;
}else{
return 1+size(node.leftChild)+size(node.rightChild);
}
}
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree();
TreeNode root = binaryTree.root;
binaryTree.createBinaryTree(root);
System.out.println(binaryTree.height(root));
System.out.println(binaryTree.size(root));
binaryTree.preOrder(root);
System.out.println("*******");
binaryTree.nonRecPreOrder(root);
System.out.println("*******");
binaryTree.nonRecInOrder(root);
System.out.println("-------------");
binaryTree.nonRecPostOrder(root);
}
}
輸出結果:
3
6
A,1
B,2
D,4
E,5
C,3
F,6
*******
A,1
B,2
D,4
E,5
C,3
F,6
*******
D,4
B,2
E,5
A,1
C,3
F,6
-------------
D,4
E,5
B,2
F,6
C,3
A,1
————————————————
版權聲明:本文為CSDN博主「專注移動開發技術」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_33275597/article/details/52759223