闵老师的文章链接: 日撸 Java 三百行(总述)_minfanphd的博客-CSDN博客
自己也把手敲的代码放在了github上维护:https://github.com/fulisha-ok/sampledata
为了提高代码的复用,java中可以通过继承,实现接口,等方式来实现
继承(extends)
其实我们每一个类都会继承超类(Object)这个是隐式继承也是java中唯一的一个隐式集成(子类自动继承超类的所有属性和方法)继承可以提高我们代码的复用性也方便维护,也可以方便我们扩展。在开发中,并不是继承越多越好,如果继承的链太长可能会导致继承爆炸从而影响系统性能,扩展也很麻烦。
接口
定义的接口类中只是定义了一组方法,但具体的是没有实现的,只有实现了这个接口才完成具体的实现,而对于不同的类实现这个接口,会有不同的逻辑,这也体现了java的动态性。这里主要体现的是接口的复用技术
包装类型主要是用来封装基本数据类型的, java中基本的8种数据类型并不是对象,可以通过包装类将其转为包装类对象。可以把基本数据类型转为包装类型,也可以把包装类型转为基本数据类型。(装箱和拆箱)。
Integer tempIndexInteger = 0; // 自动装箱,等价于 Integer tempIndexInteger = Integer.valueOf(0);
int i = new Integer(10); // 自动拆箱,等价于 int i = Integer.valueOf(10).intValue();
文章代码中:
tempIndex = (int) tempIntQueue.dequeue(); //等价于 ((Integer) tempIntQueue.dequeue()).intValue();
我认为特别要注意的是基本数据类型和包装类型在没有赋值时,系统为其赋初始值时,例如int a; 则a默认为0,而 Integer a;则默认a为null (其他类型也类似)从这也可以体现出对象和基本数据类型的差别。
java内存分配其实有助于我们去理解数据是如何存储和运行的,我认为这一篇文章写得比较易于理解,这是文章连接:点击这里
/**
* Covert the tree to data arrays, including a char array and an int array
* The results are stored in two member variables
*/
public void toDataArraysObjectQueue(){
int tempLength = getNumNodes();
valuesArray = new char[tempLength];
indicesArray = new int[tempLength];
int i = 0;
CircleObjectQueue tempQueue = new CircleObjectQueue();
tempQueue.enqueue(this);
CircleObjectQueue tempIntQueue = new CircleObjectQueue();
Integer tempIndexInteger = 0; // 自动装箱,等价于 Integer tempIndexInteger = Integer.valueOf(0);
tempIntQueue.enqueue(tempIndexInteger);
BinaryCharTree tempTree = (BinaryCharTree) tempQueue.dequeue();
int tempIndex = (int) tempIntQueue.dequeue();
System.out.println("tempIndex = " + tempIndex);
while (tempTree != null){
valuesArray[i] = tempTree.value;
indicesArray[i] = tempIndex;
i++;
if (tempTree.leftChild != null){
tempQueue.enqueue(tempTree.leftChild);
tempIntQueue.enqueue(Integer.valueOf(tempIndex * 2 + 1));
}
if (tempTree.rightChild != null) {
tempQueue.enqueue(tempTree.rightChild);
tempIntQueue.enqueue(Integer.valueOf(tempIndex * 2 + 2));
}
tempTree = (BinaryCharTree) tempQueue.dequeue();
if (tempTree == null) {
break;
}
tempIndex = (int) tempIntQueue.dequeue(); //等价于 ((Integer) tempIntQueue.dequeue()).intValue();
}
}
文章代码是用的一个数组存结点值,一个数组存结点的索引位置。
顺:在存储二叉树时,参考day22思路,采用两个数组,一个存储数据,一个存储索引结点值来存储二叉树并存储二叉树结点之间的关系。
逆:现在建立二叉树,根据两个数组来还原二叉树的关系。结合上面的图,如[a, b, c, d, e, f, g];[0, 1, 2, 4, 5, 9, 10]
对于第一个结点a,不用考虑肯定是根结点;对于第i个结点,要和那个结点有关系就要往前找(我们用的层次遍历,所以往前找,遍历i之前的结点为记为j),找符合条件的即要满足关系:i = j×2 +1 或 i=j×2+2
举例:如找c结点与那个结点有联系,则需要去遍历a,和 b两个结点其中是否有满足上面公式的,发现a满足,则表面a是c的双亲结点。
所以核心思路就是父节点和孩子结点之间的关系。i = j×2 +1 或 i=j×2+2
/**
* The parameters must be correct since no validity.check is undertaken.
* @param paraDataArray The array for data.
* @param paraIndicesArray The array for indices.
*/
public BinaryCharTree(char[] paraDataArray, int[] paraIndicesArray){
// Step 1. Use a sequential list to store all nodes.
int tempNumNodes = paraDataArray.length;
BinaryCharTree[] tempAllNodes = new BinaryCharTree[tempNumNodes];
for (int i = 0; i < tempNumNodes; i++){
tempAllNodes[i] = new BinaryCharTree(paraDataArray[i]);
}
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){
// i结点是j结点的左孩子
tempAllNodes[j].leftChild = tempAllNodes[i];
System.out.println("Linking " + j + " with " + i);
break;
}else if (paraIndicesArray[i] == paraIndicesArray[j] * 2 + 2){
// i结点是j结点的右孩子
tempAllNodes[j].rightChild = tempAllNodes[i];
System.out.println("Linking " + j + " with " + i);
break;
}
}
}
//Step 3. The root is the first node.
value = tempAllNodes[0].value;
leftChild = tempAllNodes[0].leftChild;
rightChild = tempAllNodes[0].rightChild;
}
main方法
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\nLevel-order visit:");
tempTree.levelOderVisit();
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.valuesArray));
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.valuesArray));
System.out.println("The indices are: " + Arrays.toString(tempTree.indicesArray));
System.out.println("*********************************************");
//char[] tempCharArray = {'A', 'B', 'C', 'D', 'E', 'F'};
//int[] tempIndicesArray = {0, 1, 2, 4, 5, 12};
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();
}