day12-Java(使用具有通用性的队列)

本文介绍了如何使用通用队列实现二叉树的层次遍历,同时将树转换为数据数组。讲解了Object类作为所有类的父类的角色,以及Integer与int的区别。通过代码展示了如何利用一个存储对象的队列替代两个队列来完成昨天的代码功能,重点在于代码复用的思想。文章还提供了二叉树的前序、中序和后续遍历,以及计算树的深度和节点数的方法。
摘要由CSDN通过智能技术生成

使用具有通用性的队列

前言

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

一、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

运行结果:
在这里插入图片描述

总结

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值