一丶利用二叉樹前序順序構(gòu)建二叉樹
"#" 代表空結(jié)點(diǎn)
/**
*
* A
*
* B C
*
* D E # F
*
* # # # # # #
*
*
* A B D## E## C # F ## 利用前序遍歷快速反向創(chuàng)建二叉樹
*/
public void createBinaryTreePre(ArrayList<String> data) {
createBinaryTree(data);
}
private Node createBinaryTree(ArrayList<String> data) {
if (0 == data.size()) {
return null;
}
String d = data.get(0);
if ("#".equals(d)) {
data.remove(0);
return null;
}
Node node = new Node(0, d);
data.remove(0);
if (null == root) {
root = node;
}
node.leftChild = createBinaryTree(data);
node.rightChild = createBinaryTree(data);
return node;
}
二丶遞歸實(shí)現(xiàn)二叉樹前中后序遍歷
/**
* 遞歸方式實(shí)現(xiàn)前序遍歷
*/
public void recursionPrerEgodic(Node node) {
if (null == node) {
return;
}
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
// 輸出左邊節(jié)點(diǎn) 根節(jié)點(diǎn)左邊的可以看成是一個(gè)子樹,遞歸調(diào)用此方法即可
recursionPrerEgodic(node.leftChild);
// 輸出右邊節(jié)點(diǎn)
recursionPrerEgodic(node.rightChild);
}
/**
* 遞歸方式實(shí)現(xiàn)中序遍歷
*/
public void recursionMidEgodic(Node node) {
if (null == node) {
return;
}
// 先遞歸輸出左邊的節(jié)點(diǎn)
recursionMidEgodic(node.leftChild);
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
// 最后輸出右邊節(jié)點(diǎn)
recursionMidEgodic(node.rightChild);
}
/**
* 遞歸方式實(shí)現(xiàn)后序遍歷
*/
public void recursionPostEgodic(Node node) {
if (null == node) {
return;
}
// 先遞歸輸出左邊的節(jié)點(diǎn)
recursionPostEgodic(node.leftChild);
// 最后輸出右邊節(jié)點(diǎn)
recursionPostEgodic(node.rightChild);
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
}
三丶循環(huán)實(shí)現(xiàn)二叉樹前中后序遍歷
/**
* 循環(huán)方式實(shí)現(xiàn)前序遍歷 借助棧實(shí)現(xiàn)
*/
public void loopPreEgodic(Node node) {
if (null == node) {
return;
}
// 借用棧實(shí)現(xiàn)
Stack<Node> stack = new Stack<Node>();
stack.push(node);
while (!stack.isEmpty()) {
// 從棧中取出數(shù)據(jù)。
node = stack.pop();
// 取出數(shù)據(jù)
System.out.println("數(shù)據(jù):" + node.data);
// 因?yàn)槭歉?左 右 而棧是先進(jìn)后出,所以一定要先把右邊壓入棧中 再壓入左面,
// 如果此節(jié)點(diǎn)左右節(jié)點(diǎn)不為null,將此節(jié)點(diǎn)的左右節(jié)點(diǎn)壓入棧中
if (null != node.rightChild) {
stack.push(node.rightChild);
}
if (null != node.leftChild) {
stack.push(node.leftChild);
}
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)中序遍歷 借用棧實(shí)現(xiàn)
*/
public void loopMidEgodic(Node node) {
if (null == node) {
return;
}
// 借用棧實(shí)現(xiàn)
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || null != node) {
// 先遍歷出所有左節(jié)點(diǎn)放入棧中,停止條件是node指針為null
if (null != node) {
stack.push(node);
// node指針指向左節(jié)點(diǎn)
node = node.leftChild;
} else {
// 此時(shí)取出棧中的數(shù)據(jù)
node = stack.pop();
System.out.println("數(shù)據(jù):" + node.data);
node = node.rightChild;
}
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)后序遍歷方法一 借用雙棧實(shí)現(xiàn)
*/
public void loopPostEgodic_1(Node node) {
if (null == node) {
return;
}
// 借用雙棧實(shí)現(xiàn)
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
s1.push(node);
while (!s1.isEmpty()) {
node = s1.pop();
// 先不輸出,先將根節(jié)點(diǎn)壓入棧2,最后輸出
s2.push(node);
// 注意 以下代碼順序不能換
// 放入棧1后 左在棧底 右 在棧頂,放入棧2后,左在棧頂,右在棧底 ,而根節(jié)點(diǎn)早就放在棧2底部了,
if (null != node.leftChild) {
s1.push(node.leftChild);
}
if (null != node.rightChild) {
s1.push(node.rightChild);
}
}
while (!s2.isEmpty()) {
node = s2.pop();
System.out.println("數(shù)據(jù):" + node.data);
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)后序遍歷方法二
*/
public void loopPostEgodic_2(Node node) {
if (null == node) {
return;
}
Stack<Node> stack = new Stack<Node>();
stack.push(node);
Node pre = null;
while (!stack.isEmpty()) {
pre = stack.peek();// 注意只取出不移除
if (pre.leftChild != null && node != pre.leftChild && node != pre.rightChild) {
stack.push(pre.leftChild);
}
else if (pre.rightChild != null && node != pre.rightChild) {
stack.push(pre.rightChild);
}
else {
node = stack.pop();
System.out.println("數(shù)據(jù):" + node.data);
node = pre;
}
}
}
四丶完整代碼
public class WDBinaryTree {
class Node {
int index;
String data;
Node parent;
Node leftChild;
Node rightChild;
public Node(int index, String data) {
super();
this.data = data;
this.index = index;
this.parent = null;
this.leftChild = null;
this.rightChild = null;
}
}
Node root = null;
/**
*
* A
*
* B C
*
* D E # F
*
* # # # # # #
*
*
* A B D## E## C # F ## 利用前序遍歷快速反向創(chuàng)建二叉樹
*/
public void createBinaryTreePre(ArrayList<String> data) {
createBinaryTree(data);
}
private Node createBinaryTree(ArrayList<String> data) {
if (0 == data.size()) {
return null;
}
String d = data.get(0);
if ("#".equals(d)) {
data.remove(0);
return null;
}
Node node = new Node(0, d);
data.remove(0);
if (null == root) {
root = node;
}
node.leftChild = createBinaryTree(data);
node.rightChild = createBinaryTree(data);
return node;
}
/**
* 獲取二叉樹的高度
*/
public int getHeight(Node node) {
if (null == node) {
return 0;
}
int i = getHeight(node.leftChild);
int j = getHeight(node.rightChild);
return i > j ? (i + 1) : (j + 1);
}
/**
* 獲取二叉樹的節(jié)點(diǎn)數(shù)
*/
public int getNum(Node node) {
if (null == node) {
return 0;
}
return 1 + getNum(node.leftChild) + getNum(node.rightChild);
}
/**
* 遞歸方式實(shí)現(xiàn)前序遍歷
*/
public void recursionPrerEgodic(Node node) {
if (null == node) {
return;
}
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
// 輸出左邊節(jié)點(diǎn) 根節(jié)點(diǎn)左邊的可以看成是一個(gè)子樹,遞歸調(diào)用此方法即可
recursionPrerEgodic(node.leftChild);
// 輸出右邊節(jié)點(diǎn)
recursionPrerEgodic(node.rightChild);
}
/**
* 遞歸方式實(shí)現(xiàn)中序遍歷
*/
public void recursionMidEgodic(Node node) {
if (null == node) {
return;
}
// 先遞歸輸出左邊的節(jié)點(diǎn)
recursionMidEgodic(node.leftChild);
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
// 最后輸出右邊節(jié)點(diǎn)
recursionMidEgodic(node.rightChild);
}
/**
* 遞歸方式實(shí)現(xiàn)后序遍歷
*/
public void recursionPostEgodic(Node node) {
if (null == node) {
return;
}
// 先遞歸輸出左邊的節(jié)點(diǎn)
recursionPostEgodic(node.leftChild);
// 最后輸出右邊節(jié)點(diǎn)
recursionPostEgodic(node.rightChild);
// 先輸出根節(jié)點(diǎn)
System.out.println("數(shù)據(jù):" + node.data);
}
/**
* 循環(huán)方式實(shí)現(xiàn)前序遍歷 借助棧實(shí)現(xiàn)
*/
public void loopPreEgodic(Node node) {
if (null == node) {
return;
}
// 借用棧實(shí)現(xiàn)
Stack<Node> stack = new Stack<Node>();
stack.push(node);
while (!stack.isEmpty()) {
// 從棧中取出數(shù)據(jù)。
node = stack.pop();
// 取出數(shù)據(jù)
System.out.println("數(shù)據(jù):" + node.data);
// 因?yàn)槭歉?左 右 而棧是先進(jìn)后出,所以一定要先把右邊壓入棧中 再壓入左面,
// 如果此節(jié)點(diǎn)左右節(jié)點(diǎn)不為null,將此節(jié)點(diǎn)的左右節(jié)點(diǎn)壓入棧中
if (null != node.rightChild) {
stack.push(node.rightChild);
}
if (null != node.leftChild) {
stack.push(node.leftChild);
}
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)中序遍歷 借用棧實(shí)現(xiàn)
*/
public void loopMidEgodic(Node node) {
if (null == node) {
return;
}
// 借用棧實(shí)現(xiàn)
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || null != node) {
// 先遍歷出所有左節(jié)點(diǎn)放入棧中,停止條件是node指針為null
if (null != node) {
stack.push(node);
// node指針指向左節(jié)點(diǎn)
node = node.leftChild;
} else {
// 此時(shí)取出棧中的數(shù)據(jù)
node = stack.pop();
System.out.println("數(shù)據(jù):" + node.data);
node = node.rightChild;
}
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)后序遍歷方法一 借用雙棧實(shí)現(xiàn)
*/
public void loopPostEgodic_1(Node node) {
if (null == node) {
return;
}
// 借用雙棧實(shí)現(xiàn)
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
s1.push(node);
while (!s1.isEmpty()) {
node = s1.pop();
// 先不輸出,先將根節(jié)點(diǎn)壓入棧2,最后輸出
s2.push(node);
// 注意 以下代碼順序不能換
// 放入棧1后 左在棧底 右 在棧頂,放入棧2后,左在棧頂,右在棧底 ,而根節(jié)點(diǎn)早就放在棧2底部了,
if (null != node.leftChild) {
s1.push(node.leftChild);
}
if (null != node.rightChild) {
s1.push(node.rightChild);
}
}
while (!s2.isEmpty()) {
node = s2.pop();
System.out.println("數(shù)據(jù):" + node.data);
}
}
/**
* 循環(huán)方式實(shí)現(xiàn)后序遍歷方法二
*/
public void loopPostEgodic_2(Node node) {
if (null == node) {
return;
}
Stack<Node> stack = new Stack<Node>();
stack.push(node);
Node pre = null;
while (!stack.isEmpty()) {
pre = stack.peek();// 注意只取出不移除
if (pre.leftChild != null && node != pre.leftChild && node != pre.rightChild) {
stack.push(pre.leftChild);
}
else if (pre.rightChild != null && node != pre.rightChild) {
stack.push(pre.rightChild);
}
else {
node = stack.pop();
System.out.println("數(shù)據(jù):" + node.data);
node = pre;
}
}
}
/**
* 層序 利用隊(duì)列實(shí)現(xiàn)
*/
public void levelEgodic(Node node) {
if (null == node) {
return;
}
Queue<Node> q = new LinkedList<Node>();
q.add(node);
while (!q.isEmpty()) {
//源碼: Retrieves and removes the head of this queue,
node = q.poll();// 取出并移除
System.out.println("數(shù)據(jù):" + node.data);
if (null != node.leftChild) {
q.add(node.leftChild);
}
if (null != node.rightChild) {
q.add(node.rightChild);
}
}
}
public static void main(String[] args) {
//二叉樹的前序遍歷順序,#代表空結(jié)點(diǎn)
String[] data = { "A", "B", "D", "#", "#", "E", "#", "#", "C", "#", "F", "#", "#" };
ArrayList<String> dataList = new ArrayList<String>();
for (String s : data) {
dataList.add(s);
}
//構(gòu)造二叉樹
WDBinaryTree tree = new WDBinaryTree();
tree.createBinaryTreePre(dataList);
int i = tree.getHeight(tree.root);
int num = tree.getNum(tree.root);
System.out.println("二叉樹的高度為:" + i);
System.out.println("二叉樹的節(jié)點(diǎn)數(shù)為:" + num);
System.out.println("遞歸實(shí)現(xiàn)--");
System.out.println("前序:");
tree.recursionPrerEgodic(tree.root);
System.out.println("中序:");
tree.recursionMidEgodic(tree.root);
System.out.println("后序:");
tree.recursionPostEgodic(tree.root);
// 遞歸調(diào)用一個(gè)方法,相當(dāng)于將數(shù)據(jù)加入一個(gè)棧中,先進(jìn)后出
System.out.println("循環(huán)實(shí)現(xiàn)--");
System.out.println("前序:");
tree.loopPreEgodic(tree.root);
System.out.println("中序:");
tree.loopMidEgodic(tree.root);
System.out.println("后序1:");
tree.loopPostEgodic_1(tree.root);
System.out.println("后序2:");
tree.loopPostEgodic_2(tree.root);
System.out.println("層序:");
tree.levelEgodic(tree.root);
}
}
五丶測試結(jié)果

圖片.png

圖片.png