二叉树节点的表示法:
- 二叉树数组表示法
- 二叉树链表表示法
“数组表示法”属于静态内存空间配置,而“链表表示法”是利用链表结构的方式,属于动态内存空间配置。、
二叉树数组表示法
/**
* 树节点的定义
*/
class TreeNode
{
int val;
TreeNode left; // 左子树节点
TreeNode right; // 右子树节点
TreeNode(int x)
{
val = x;
}
}
/**
* 二叉树的顺序存储结构
*/
class BinaryTree
{
private int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
private static List<TreeNode> nodeList = null;
/**
* 树节点的定义
*/
private class TreeNode
{
int val;
TreeNode left; // 左子树节点
TreeNode right; // 右子树节点
TreeNode(int x)
{
left = null;
right = null;
val = x;
}
}
public BinaryTree()
{
createBiTree();
// nodeList中第0个索引处的值即为根节点
TreeNode root = nodeList.get(0);
System.out.println("先序遍历:");
preOrderTraverse(root);
System.out.println();
System.out.println("中序遍历:");
inOrderTraverse(root);
System.out.println();
System.out.println("后序遍历:");
postOrderTraverse(root);
}
/**
* 构造一棵满二叉树
*/
private void createBiTree()
{
nodeList = new LinkedList<TreeNode>();
// 将TreeNode节点加入到链表中
for (int nodeIndex=0; nodeIndex<array.length; nodeIndex++)
{
nodeList.add(new TreeNode(array[nodeIndex]));
}
// 对前lastParentIndex-1个父节点按照父节点与孩子节点的数字关系建立二叉树
for (int parentIndex=0; parentIndex<array.length/2-1; parentIndex++)
{
// 左孩子
nodeList.get(parentIndex).left = nodeList.get(parentIndex*2+1);
// 右孩子
nodeList.get(parentIndex).right = nodeList.get(parentIndex*2+2);
}
// 最后一个父节点:因为最后一个父节点可能没有右孩子,所以单独拿出来处理
int lastParentIndex = array.length / 2 - 1;
// 左孩子
nodeList.get(lastParentIndex).left = nodeList.get(lastParentIndex*2+1);
// 右孩子,如果数组的长度为奇数才建立右孩子
if (array.length % 2 == 1)
{
nodeList.get(lastParentIndex).right = nodeList.get(lastParentIndex*2+2);
}
}
/**
* 先序遍历
*/
public static void preOrderTraverse(TreeNode node)
{
if (node == null)
{
return;
}
System.out.print(node.val + " ");
// 遍历左子树
preOrderTraverse(node.left);
// 遍历右子树
preOrderTraverse(node.right);
}
/**
* 中序遍历
*/
public static void inOrderTraverse(TreeNode node)
{
if (node == null)
{
return;
}
// 遍历左子树
inOrderTraverse(node.left);
System.out.print(node.val + " ");
// 遍历右子树
inOrderTraverse(node.right);
}
/**
* 后序遍历
*/
public static void postOrderTraverse(TreeNode node)
{
if (node == null)
{
return;
}
// 遍历左子树
postOrderTraverse(node.left);
// 遍历右子树
postOrderTraverse(node.right);
System.out.print(node.val + " ");
}
}
二叉树链表表示法
/**
* 二叉树的链式存储结构
* https://www.cnblogs.com/Dylansuns/p/6791852.html
*/
public class BinaryTree<E>
{
/**
* 树节点的定义
*/
class TreeNode
{
Object data;
TreeNode left; // 左子树节点
TreeNode right; // 右子树节点
TreeNode()
{
}
TreeNode(Object data)
{
this.data = data;
}
TreeNode(Object data, TreeNode left, TreeNode right)
{
this.data = data;
this.left = left;
this.right = right;
}
}
private TreeNode root;
// 以默认的构造器创建二叉树
public BinaryTree()
{
this.root = new TreeNode();
}
// 以指定根元素创建二叉树
public BinaryTree(E data)
{
this.root = new TreeNode(data);
}
/**
* 为指定节点添加子节点
*/
public TreeNode addNode(TreeNode parent, E data, boolean isLeft)
{
if (parent == null)
{
throw new RuntimeException(parent + "节点为null, 无法添加子节点");
}
if (isLeft && parent.left != null)
{
throw new RuntimeException(parent + "节点已有左子节点,无法添加左子节点");
}
if (!isLeft && parent.right != null)
{
throw new RuntimeException(parent + "节点已有右子节点,无法添加右子节点");
}
// 创建一个新节点
TreeNode newNode = new TreeNode(data);
if (isLeft)
{
// 让父节点的left引用指向新节点
parent.left = newNode;
}
else
{
// 让父节点的right引用指向新节点
parent.right = newNode;
}
return newNode;
}
// 判断二叉树是否为空
public boolean empty()
{
return root.data==null;
}
// 返回根节点
public TreeNode root()
{
if (empty())
{
throw new RuntimeException("树为空,无法访问根节点");
}
return root;
}
// 返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null
public E leftChild(TreeNode parent) {
if (parent == null) {
throw new RuntimeException(parent + "节点为null,无法添加子节点");
}
return parent.left == null ? null : (E) parent.left.data;
}
// 返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null
public E rightChild(TreeNode parent) {
if (parent == null) {
throw new RuntimeException(parent + "节点为null,无法添加子节点");
}
return parent.right == null ? null : (E) parent.right.data;
}
// 返回二叉树的深度
public int deep()
{
return deep(root);
}
// 这是一个递归方法:每一棵子树的深度为其所有子树的最大深度 + 1
public int deep(TreeNode node)
{
if (node == null)
{
return 0;
}
// 没有子树
if (node.left == null && node.right == null)
{
return 1;
} else
{
int leftDeep = deep(node.left);
int rightDeep = deep(node.right);
// 记录其所有左、右子树中较大的深度
int max = leftDeep > rightDeep ? leftDeep : rightDeep;
// 返回其左右子树中较大的深度 + 1
return max + 1;
}
}
// 测试
public static void main(String[] args)
{
BinaryTree<String> binTree = new BinaryTree<String>("根节点");
// 依次添加节点
BinaryTree.TreeNode tn1 = binTree.addNode(binTree.root(), "第二层左节点", true);
BinaryTree.TreeNode tn2 = binTree.addNode(binTree.root(), "第二层右节点", false);
BinaryTree.TreeNode tn3 = binTree.addNode(tn2, "第三层左节点", true);
BinaryTree.TreeNode tn4 = binTree.addNode(tn2, "第三层右节点", false);
BinaryTree.TreeNode tn5 = binTree.addNode(tn3, "第四层左节点", true);
System.out.println("tn2的左子节点:" + binTree.leftChild(tn2));
System.out.println("tn2的右子节点:" + binTree.rightChild(tn2));
System.out.println(binTree.deep());
}
}