day11-Java(二叉树的存储)

本文介绍了二叉树的顺序存储结构,包括如何使用循环列表存储完全二叉树,并探讨了顺序存储的优缺点。接着详细讲解了BFS遍历,通过代码展示了如何进行层序遍历,并对比了层序遍历与BFS遍历的区别。最后提供了代码测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉树的存储

一、顺序存储结构

二叉树的顺序存储是指用一组地址连续的存储单元依次自上而下,自左至右存储完全二叉树上的节点元素,老师的代码中使用的是前面使用过的循环列表对二叉树进行存储。
对于一般的二叉树(如代码中构建的二叉树),为了让数组下标能反映二叉树中结点之间的逻辑关系,只能添加一些并不存在的空节点,让其每个节点与完全二叉树上的结点相对照,再存储到一维数组的对应分量中。昨天的二叉树如下图:
在这里插入图片描述
用一个向量来存储:
[a, b, c, 0, d, e, 0, 0, 0, f, g]
优点:仅需要一个向量,简单粗暴
缺点:对于实际的二叉树,很多子树为空,导致大量的0值。
在最坏的情况下,一个高度为h且只有h个节点的单支树却需要占据近 2 h − 1 {2^h -1} 2h1个存储空间。
使用顺序存储结构存储二叉树还需注意父节点与子节点在同一向量中,对应序号的数学关系:
n L e f t C h i l d = 2 ∗ n R o o t + 1 {n_{LeftChild} = 2 * n_{Root} + 1} nLeftChild=2nRoot+1
n R i g h t C h i l d = 2 ∗ n R o o t + 2 {n_{RightChild} = 2 * n_{Root} + 2} nRightChild=2nRoot+2

二、BFS遍历

在这里插入图片描述
这段代码中,遍历的过程即是在循环队列中插入二叉树节点的过程。代码如下:

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

在查阅BFS遍历资料时,发现层序遍历这个遍历算法,对二叉树的遍历,层序遍历可以返回一个二维数组,而BFS的遍历结果只是一个一维数组。

三、代码与数据测试

今天的代码是在昨天的二叉树代码上加写的。

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

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

} // Of BinaryCharTree

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值