文章目录

  • 使用具有通用性的队列
  • 前言
  • 一、Object类简介
  • 二、 关于Integer
  • 三、代码实现
  • 四、代码与数据测试
  • 总结


使用具有通用性的队列

前言

今天的这段代码初看与昨天的很相似,准确来说,所实现的功能确实都是一样的,但是今天的代码中传递了一个重要的编程思想–类复用(代码复用)。

一、Object类简介

Object类是Javajava.lang包下的核心类,Object类是所有类的父类,任何一个类如果没有明确的继承一个父类的话,那么它就是Object的子类。例如

public class CircleObjectQueue; 等价于
public class CircleObjectQueue extends Object;

二、 关于Integer

Java 本身将 int, double, char 分别封装到 Integer, Double, Char 类.
Integer类int区别:

  1. Integer 是 int 包装类,final修饰,int 是八大基本数据类型之一(byte,char,short,int,long,float,double,boolean)
  2. Integer 是类,默认值为null,int是基本数据类型,默认值为0;
  3. Integer 表示的是对象,用一个引用指向这个对象,而int是基本数据类型,直接存储数值。
Integer tempIndexInteger = Integer.valueOf(0);

上面代码是将字串"0"的类型转换为integer。

三、代码实现

与昨天的代码一样,用getNumNodes()函数获取二叉树的节点数,因为要把各个节点存入队列,所以队列长度就为节点数:
int tempLength = getNumNodes();
使用char[tempLength]创建数组,把新创建的数组的引用复制给变量valuesArray与indicesArray:
valuesArray = new char[tempLength];indicesArray = new int[tempLength];

创建一个存放二叉树节点Value的队列,一个存放节点索引的队列。tempIntQueue队列创建与昨天的代码中不同,昨天使用的队列有两种:存储二叉树节点的队列;存储整数的队列。今天将利用代码的复用性,用一个存储对象的队列实现昨天两个队列完成的功能。
存储对象的队列, 实际上是存储对象的地址 (引用、指针). 因此, 可以存储任何类的对象 (的引用).代码如下:

// Traverse and convert at the same time.
		CircleObjectQueue tempQueue = new CircleObjectQueue();
		tempQueue.enqueue(this);
		CircleObjectQueue tempIntQueue = new CircleObjectQueue();
		Integer tempIndexInteger = Integer.valueOf(0);
		tempIntQueue.enqueue(tempIndexInteger);

这里还有个没有明白的地方就是tempQueue.enqueue(this)中的this,参考前后代码可知,这里的this应该指的是二叉树节点存储的对象。但是不明白为什么这个地方可以用this。

四、代码与数据测试

package datastructure.tree;

import java.util.Arrays;
import datastructure.queue.*;
/**
 * Binary tree with char type elements.
 *
 * @auther Weijie Pu weijiepu@163.com.
 */
public class BinaryCharTree {

	/**
	 * The value in char.
	 */
	char value;

	/**
	 * The left child.
	 */
	BinaryCharTree leftChild;

	/**
	 * The right child.
	 */
	BinaryCharTree rightChild;

	/**
	 *********************
	 * The first constructor.
	 * 
	 * @param paraName
	 *            The value.
	 *********************
	 */
	public BinaryCharTree(char paraName) {
		value = paraName;
		leftChild = null;
		rightChild = null;
	} // Of the constructor

	/**
	 ********************
	 * Mannually construct a tree. Only for testing.
	 ********************
	 */
	public static BinaryCharTree manualConstructTree() {
		// Step 1. Construct a tree with only one node.
		BinaryCharTree resultTree = new BinaryCharTree('a');

		// Step 2. Construct all nodes. The first node is the root.
		// BinaryCharTreeNode tempTreeA = resultTree.root;
		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');

		// Step 3. Link all nodes.
		resultTree.leftChild = tempTreeB;
		resultTree.rightChild = tempTreeC;
		tempTreeB.rightChild = tempTreeD;
		tempTreeC.leftChild = tempTreeE;
		tempTreeD.leftChild = tempTreeF;
		tempTreeD.rightChild = tempTreeG;

		return resultTree;
	} // Of maualConstructTree

	/**
	 ********************
	 * Pre-order visit.
	 ********************
	 */
	public void preOrderVisit() {
		System.out.print("" + value + " ");

		if (leftChild != null) {
			leftChild.preOrderVisit();
		} // Of if

		if (rightChild != null) {
			rightChild.preOrderVisit();
		} // Of if
	} // Of preOrderVisit

	/**
	 ********************
	 * In-order visit.
	 ********************
	 */
	public void inOrderVisit() {
		if (leftChild != null) {
			leftChild.inOrderVisit();
		} // Of if

		System.out.print("" + value + " ");

		if (rightChild != null) {
			rightChild.inOrderVisit();
		} // Of if
	} // Of inOrderVisit

	/**
	 ********************
	 * Post-order visit.
	 ********************
	 */
	public void postOrderVisit() {
		if (leftChild != null) {
			leftChild.postOrderVisit();
		} // Of if

		if (rightChild != null) {
			rightChild.postOrderVisit();
		} // Of if

		System.out.print("" + value + " ");
	} // Of postOrderVisit

	/**
	 ********************
	 * Get the depth of the binary tree.
	 *
	 * @return The depth. It is 1 if there is only one node. i.e., the root.
	 ********************
	 */
	public int getDepth() {
		// It is a leaf.
		if ((leftChild == null) && (rightChild == null)) {
			return 1;
		} // Of if

		// The depth of the left child.
		int tempLeftDepth = 0;
		if (leftChild != null) {
			tempLeftDepth = leftChild.getDepth();
		} // Of if

		// The depth of the right child.
		int tempRightDepth = 0;
		if (rightChild != null) {
			tempRightDepth = rightChild.getDepth();
		} // Of if

		// The depth should increment by 1.
		if (tempLeftDepth >= tempRightDepth) {
			return tempLeftDepth + 1;
		} else {
			return tempRightDepth + 1;
		} // Of if
	} // Of getDepth

	/**
	 ********************
	 * Get the number of nodes.
	 *
	 * @return The number of nodes.
	 ********************
	 */
	public int getNumNodes() {
		// It is a leaf.
		if ((leftChild == null) && (rightChild == null)) {
			return 1;
		} // Of if

		// The number of nodes of the left child.
		int tempLeftNodes = 0;
		if (leftChild != null) {
			tempLeftNodes = leftChild.getNumNodes();
		} // Of if

		// The number of nodes of the right child.
		int tempRightNodes = 0;
		if (rightChild != null) {
			tempRightNodes = rightChild.getNumNodes();
		} // Of if

		// The total number of nodes.
		return tempLeftNodes + tempRightNodes + 1;
	}
	
	/**
	 * The values of nodes according to breadth first traversal.
	 */
	char[] valuesArray;

	/**
	 * The indices in the complete binary tree.
	 */
	int[] indicesArray;

	/**
	 ********************
	 * Convert the tree to data arrays, including a char array and an int array.
	 * The results are stored in two member variables.
	 * 
	 * @see #valuesArray
	 * @see #indicesArray
	 *********************
	 */
	public void toDataArrays() {
		//Initialize arrays.
		int tempLength = getNumNodes();

		valuesArray = new char[tempLength];
		indicesArray = new int[tempLength];
		int i = 0;

		//Traverse and convert at the same time.
		CircleObjectQueue tempQueue = new CircleObjectQueue();
		tempQueue.enqueue(this);
		CircleIntQueue tempIntQueue = new CircleIntQueue();
		tempIntQueue.enqueue(0);

		BinaryCharTree tempTree = (BinaryCharTree) tempQueue.dequeue();
		int tempIndex = tempIntQueue.dequeue();
		while (tempTree != null) {
			valuesArray[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();
			tempIndex = tempIntQueue.dequeue();
		} // Of while
	}// Of toDataArrays
	
	/**
	 ********************
	 * Convert the tree to data arrays, including a char array and an int array.
	 * The results are stored in two member variables.
	 * 
	 * @see #valuesArray
	 * @see #indicesArray
	 ********************
	 */
	public void toDataArraysObjectQueue() {
		// Initialize arrays.
		int tempLength = getNumNodes();
		
		valuesArray = new char[tempLength];
		indicesArray = new int[tempLength];
		int i = 0;
		
		// Traverse an convert at the same time.
		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) {
			valuesArray[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

	/**
	 ********************
	 * 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.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));
	} // Of main

} // Of BinaryCharTree

运行结果:

java 入参一个对象obj java object int_开发语言

总结

个人感觉这两天的代码难度一下子上去了,之前的代码都是写的时间大于思考的时间,现在是思考的时间远大于写代码的时间。在学习数据结构时,二叉树便是一个不可忽视的重点,但更多的是学会相关的算法,一到存储这一块就不行了,特别是顺序存储结构,到链式存储应该会好一点,毕竟树的链式存储也会更形象一点。