昨天二叉树的存储为今天的二叉树创建做了铺垫,即从两个数组中抽象出二叉树。只要把昨天的理清了,今天就不是特别难。
声明一个双参构造方法,参数为二叉树节点值数组与索引数组
/**
*********************
* 第二个构造方法 通过参数创建二叉树
*
* @param paraDataArray 节点值数组
* @param paraIndicesArray 索引数组
*********************
*/
public BinaryCharTree(char[] paraDataArray, int[] paraIndicesArray) {
// Step 1. 用一个object类型的顺序表来存储节点
int tempnodes = paraDataArray.length;
BinaryCharTree tempAllNodes[] = new BinaryCharTree[tempnodes];
for (int i = 0; i < tempnodes; ++i) {
tempAllNodes[i] = new BinaryCharTree(paraDataArray[i]);
}//of for i
通过两个数组间的逻辑关系,构建二叉树:
// Step 2. 通过参数传递的信息来link二叉树
for (int i = 0; i <( paraIndicesArray[tempnodes-1]-1)/2; ++i) {
for (int j = i + 1; j < tempnodes; j++) {
if (paraIndicesArray[i] * 2 + 1 == paraIndicesArray[j]) {
tempAllNodes[i].leftChild = tempAllNodes[j];
System.out.println("indices " + paraIndicesArray[i] + " vs. " + paraIndicesArray[j]);
}// of if
else if (paraIndicesArray[i] * 2 + 2 == paraIndicesArray[j]) {
tempAllNodes[i].rightChild = tempAllNodes[j];
System.out.println("indices " + paraIndicesArray[i] + " vs. " + paraIndicesArray[j]);
break;
}//of else if
else if(paraIndicesArray[i] * 2 + 2 <paraIndicesArray[j]){
break;
}
}//of for j
}//of for i
value = tempAllNodes[0].value;
leftChild = tempAllNodes[0].leftChild;
rightChild = tempAllNodes[0].rightChild;
}//of BinaryCharTree
思路:记 i 为父节点,j 为孩子节点,遍历并找到符合当前 i 的 j。优化一下,发现不是所有的 i 都能当父节点,找下规律,调整 i 的遍历范围:i<(最大索引值-1)/2; 若右孩子确定直接break;如果当前父节点理论右孩子的索引小于判定 j 的索引 说明当前父节点没有右孩子,break;这样既限制了父节点 i 的无效遍历,也限制了 孩子节点 j 的无效遍历,如果能够判断哪些节点是兄弟关系,还能进一步优化 j ,可惜没想到怎么做。
主函数:
/**
* ********************
* The entrance of the program.
*
* @param args Not used now.
* ********************
*/
public static void main(String args[]) {
char[] tempCharArray = { 'a', 'b', 'c', 'd', 'e', 'f','g' };
int[] tempIndicesArray = { 0, 1, 2, 4, 5, 9, 10 };
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();
}// Of main
运行效果:
对比一下老师的代码,发现有一点不一样,i,j 怎么和我是反着的,哦原来老师是通过孩子节点来找父节点,i 代表孩子节点,遍历 j 找父节点,由于一个孩子只能有一个父,所以一旦找到了就break,这也太反人类的常规思路,不过学到了,换个角度就是另一种写法。
for(int i=0;i<tempnodes;++i){
for(int j=0;j<tempnodes;j++){
System.out.println("indices " + paraIndicesArray[j] + " vs. " + paraIndicesArray[i]);
if(paraIndicesArray[i]==paraIndicesArray[j]*2+1){
tempAllNodes[j].leftChild=tempAllNodes[i];
break;
}
else if(paraIndicesArray[i]==paraIndicesArray[j]*2+2){
System.out.println("indices " + paraIndicesArray[j] + " vs. " + paraIndicesArray[i]);
tempAllNodes[j].rightChild=tempAllNodes[i];
break;
}
}
}