Day 25
1. Background
今天是学习java的第25天,今天学习的是objectStack,以及用这个实现二叉树的中序遍历。
2. Description
2.1About
今天的代码是先用Object类来实现栈,以实现一个代码实现所有的数据类型的效果。
所以栈的实现的代码直接把之前栈的代码搬过来,然后修修补补即可。
然后就是中序遍历了,这个倒是让我想了很久。
2.2 in-order vistit
我的理解是先建立一个栈,然后创建一个tempNode
,用这个来存要遍历的节点。
然后利用栈先进先出的特性,只要tempNode
不为空,就把这个节点压入栈中,然后向它的左孩子遍历。
而当tempNode
遍历到空之后,则说明已经到了树的最左边。
此时就可以开始出栈了,由于栈后进先出的特性,最左边的那个节点就被输出。
3. Code
3.1 Object Stack
package datastructure;
public class ObjectStack {
/**
* The depth.
*/
public static final int MAX_DEPTH = 10;
/**
* The actual depth.
*/
int depth;
/**
* The data.
*/
Object[] data;
/**
* Construct an empty object stack.
*/
public ObjectStack() {
depth = 0;
data = new Object[MAX_DEPTH];
} // Of the first constructor
public String toString() {
String resultString = "";
for (int i = 0; i < depth; i++) {
resultString += data[i];
} // Of for i
return resultString;
} // Of toString
/**
*************
* Push an element.
* @param paraChar The given element.
* @return Success or not.
* ************
*/
public boolean Push(Object paraObject) {
if (depth == MAX_DEPTH) {
System.out.println("Stack full");
return false;
} // Of if
data[depth] = paraObject;
depth++;
return true;
} // Of Push
/**
*************
* Pop an element.
* @return The poped char.
* ************
*/
public Object Pop() {
if (depth == 0) {
System.out.println("Nothing to pop");
return '\0';
} // Of if
Object resultObject = data[depth - 1];
depth--;
return resultObject;
} // Of Pop
/**
*
* 判断栈是否为空。
*
* @return Empty or not empty.
*/
public boolean isEmpty() {
if (depth == 0) {
return true;
} // Of if
return false;
} // Of isEmpty
public static void main(String[] args) {
ObjectStack tempStack = new ObjectStack();
for (char ch = 'a'; ch < 'm'; ch++) {
tempStack.Push(new Character(ch));
System.out.println("The current stack is: " + tempStack);
} // Of for i
char tempChar;
for (int i = 0; i < 12; i++) {
tempChar = ((Character)tempStack.Pop()).charValue();
System.out.println("Poped: " + tempChar);
System.out.println("The current stack is: " + tempStack);
} // Of for i
}
}
运行结果:
3.2 中序遍历
package datastructure;
import java.util.Arrays;
public class BinaryCharTree {
/**
* The value of node.
*/
char value;
/**
* 二叉树的左孩子。
*/
BinaryCharTree leftChild;
/**
* 二叉树的右孩子。
*/
BinaryCharTree rightChild;
/**
**************
* The first constructor.
*
* @param paraValue The given value.
**************
*/
public BinaryCharTree(char paraValue) {
value = paraValue;
leftChild = null;
rightChild = null;
} // Of the first construe
/**
**************
* Reload BinaryCharTree.
*
* @param paraDataArray
* @param paraIndicesArray
**************
*/
public BinaryCharTree(char[] paraDataArray, int[] paraIndicesArray) {
// Step 1. 把二叉树存到顺序表中。
int tempNumNodes = paraDataArray.length;
BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes];
for (int i = 0; i < tempNumNodes; i++) {
tempAllNodes[i] = new BinaryCharTree(paraDataArray[i]);
} // Of for i
// Step 2. Link nodes.
for (int i = 1; i < tempNumNodes; i++) {
for (int j = 0; j < i; j++) {
System.out.println("indices " + paraIndicesArray[j] + " vs. " + paraIndicesArray[i]);
if (paraIndicesArray[i] == paraIndicesArray[j] * 2 + 1) { // 节点序号从0开始,故此处为左孩子
tempAllNodes[j].leftChild = tempAllNodes[i];
System.out.println("Linking " + j + " with " + i);
break;
} else if (paraIndicesArray[i] == paraIndicesArray[j] * 2 + 2) {
tempAllNodes[j].rightChild = tempAllNodes[i];
System.out.println("Linking " + j + " with " + i);
break;
} // Of if
} // Of for j
} // Of for i
// 返回二叉树的根节点
value = tempAllNodes[0].value;
leftChild = tempAllNodes[0].leftChild;
rightChild = tempAllNodes[0].rightChild;
} // Of the the second constructor
public static BinaryCharTree manualConstructTree() {
// step 1. Creat root.
BinaryCharTree resultTree = new BinaryCharTree('a');
// step 2. creat children and linked them.
BinaryCharTree tempTreeB = new BinaryCharTree('b');
BinaryCharTree tempTreeC = new BinaryCharTree('c');
BinaryCharTree tempTreeD = new BinaryCharTree('d');
BinaryCharTree tempTreeE = new BinaryCharTree('e');
BinaryCharTree tempTreeF = new BinaryCharTree('f');
BinaryCharTree tempTreeG = new BinaryCharTree('g');
// Link strat
resultTree.leftChild = tempTreeB;
resultTree.rightChild = tempTreeC;
tempTreeB.rightChild = tempTreeD;
tempTreeC.leftChild = tempTreeE;
tempTreeD.leftChild = tempTreeF;
tempTreeD.rightChild = tempTreeG;
return resultTree;
} // Of manualConstructTree
/**
**************
* 先根、中根、后根遍历树。
**************
*/
public void preOrderVisit() {
System.out.print(value + " ");
if (leftChild != null) {
leftChild.preOrderVisit();
} // Of if
if (rightChild != null) {
rightChild.preOrderVisit();
} // Of if
} // Of preOrderVisit
public void inOrderVisit() {
if (leftChild != null) {
leftChild.inOrderVisit();
} // Of if
System.out.print(value + " ");
if (rightChild != null) {
rightChild.inOrderVisit();
} // Of if
}
public void postOrderVisit() {
if (leftChild != null) {
leftChild.postOrderVisit();
} // Of if
if (rightChild != null) {
rightChild.postOrderVisit();
} // Of if
System.out.print(value + " ");
}
public int getDepth() {
if ((leftChild == null) && (rightChild == null)) {
return 1;
} // Of if
// check left
int tempLeftDepth = 0;
if (leftChild != null) {
tempLeftDepth = leftChild.getDepth();
} // Of if
// Check right
int tempRightDepth = 0;
if (rightChild != null) {
tempRightDepth = rightChild.getDepth();
} // Of if
if (tempLeftDepth >= tempRightDepth) {
return tempLeftDepth + 1;
} else {
return tempRightDepth + 1;
} // Of if
} // Of getDepth
// 遍历时存储节点中的值。
char[] valueArray;
// 二叉树的索引。
int[] indicesArray;
public void toDataArrays() {
int tempLength = getNumNodes();
valueArray = new char[tempLength];
indicesArray = new int[tempLength];
int i = 0;
CircleObjectQueue tempQueue = new CircleObjectQueue();
tempQueue.enQueue(this);
CircleObjectQueue tempIntQueue = new CircleObjectQueue();
tempIntQueue.enQueue(0);
BinaryCharTree tempTree = (BinaryCharTree) tempQueue.deQueue();
int tempIndex = (int) tempIntQueue.deQueue();
while (tempTree != null) {
valueArray[i] = tempTree.value;
indicesArray[i] = tempIndex;
i++;
if (tempTree.leftChild != null) {
tempQueue.enQueue(tempTree.leftChild);
tempIntQueue.enQueue(tempIndex * 2 + 1);
} // Of if
if (tempTree.rightChild != null) {
tempQueue.enQueue(tempTree.rightChild);
tempIntQueue.enQueue(tempIndex * 2 + 2);
} // Of if
tempTree = (BinaryCharTree) tempQueue.deQueue();
if (tempTree != null)
tempIndex = (int) tempIntQueue.deQueue();
} // Of while
}
public int getNumNodes() {
if ((leftChild == null) && (rightChild == null)) {
return 1;
} // Of if
int tempLeftNodes = 0;
if (leftChild != null) {
tempLeftNodes = leftChild.getNumNodes();
} // Of if
int tempRightNodes = 0;
if (rightChild != null) {
tempRightNodes = rightChild.getNumNodes();
} // Of if
return tempLeftNodes + tempRightNodes + 1;
}// Of getNumNodes
public void toDataArraysObjectQueue() {
int tempLength = getNumNodes();
valueArray = new char[tempLength];
indicesArray = new int[tempLength];
int i = 0;
// 将object对象转换为想要的数据类型。
CircleObjectQueue tempQueue = new CircleObjectQueue();
tempQueue.enQueue(this);
CircleObjectQueue tempIntQueue = new CircleObjectQueue();
Integer tempIndexInteger = Integer.valueOf(0);
tempIntQueue.enQueue(tempIndexInteger);
BinaryCharTree tempTree = (BinaryCharTree) tempQueue.deQueue();
int tempIndex = ((Integer) tempIntQueue.deQueue()).intValue();
System.out.println("tempIndex = " + tempIndex);
while (tempTree != null) {
valueArray[i] = tempTree.value;
indicesArray[i] = tempIndex;
i++;
if (tempTree.leftChild != null) {
tempQueue.enQueue(tempTree.leftChild);
tempIntQueue.enQueue(Integer.valueOf(tempIndex * 2 + 1));
} // Of if
if (tempTree.rightChild != null) {
tempQueue.enQueue(tempTree.rightChild);
tempIntQueue.enQueue(Integer.valueOf(tempIndex * 2 + 2));
} // Of if
tempTree = (BinaryCharTree) tempQueue.deQueue();
if (tempTree == null) {
break;
}//Of if
tempIndex = ((Integer) tempIntQueue.deQueue()).intValue();
} // Of while
}// Of toDataArraysObjectQueue
public void inOrderVisitWithStack() {
ObjectStack tempStack = new ObjectStack();
BinaryCharTree tempNode = this;
while (!tempStack.isEmpty() || tempNode != null) {
if (tempNode != null) {
tempStack.Push(tempNode);
tempNode = tempNode.leftChild;
} else {
tempNode = (BinaryCharTree) tempStack.Pop();
System.out.print("" + tempNode.value + " ");
tempNode = tempNode.rightChild;
} // Of if
} // Of while
}// Of inOrderVisit
/**
*********************
* The entrance of the program.
*
* @param args Not used now.
*********************
*/
public static void main(String args[]) {
BinaryCharTree tempTree = manualConstructTree();
System.out.println("\r\nPreorder visit:");
tempTree.preOrderVisit();
System.out.println("\r\nIn-order visit:");
tempTree.inOrderVisit();
System.out.println("\r\nPost-order visit:");
tempTree.postOrderVisit();
System.out.println("\r\n\r\nThe depth is: " + tempTree.getDepth());
System.out.println("The number of nodes is: " + tempTree.getNumNodes());
tempTree.toDataArrays();
System.out.println("The values are: " + Arrays.toString(tempTree.valueArray));
System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));
tempTree.toDataArraysObjectQueue();
System.out.println("Only object queue.");
System.out.println("The values are: " + Arrays.toString(tempTree.valueArray));
System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));
char[] tempCharArray = {'A', 'B', 'C', 'D', 'E', 'F'};
int[] tempIndicesArray = {0, 1, 2, 4, 5, 12};
BinaryCharTree tempTree2 = new BinaryCharTree(tempCharArray, tempIndicesArray);
System.out.println("\r\nPreorder visit:");
tempTree2.preOrderVisit();
System.out.println("\r\nIn-order visit:");
tempTree2.inOrderVisit();
System.out.println("\r\nPost-order visit:");
tempTree2.postOrderVisit();
System.out.println("\r\nIn-order visit with stack:");
tempTree2.inOrderVisitWithStack();
}// Of main
}
运行结果:
4. Summarize
今天的代码有一个我比较在意的地方,VScode报出了worning,但是没有报错。
VSCode的提示是Character
在这里不适用,构造函数 Character(char) 自版本 9 起已被弃用并标记为删除。同时给出了推荐的函数valueOf(),但是我查了一下资料,valueOf貌似在这里并不适用。(因为我用了之后一直报错🤣)
途中是valueOf的用法: