一、二叉完全树是什么?
完全二叉树是由满二叉树而引出来的,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。下面来放一张完全二叉树示例图
可以看到上面的二叉树都是在当前层达到最大节点,然后再往下一层从左往右添加新的节点,一定要注意是从左往右。
然后我们看下面的图片,这就不是完全二叉树,因为它不满足我们上面所说的从左往右放,要理解这一点,对我们以后用程序实现创建完全二叉树垫下基础。
二、实现完全二叉树
1.建立树节点
这个代码在我之前的博文里就已给出(做了一点修改),但为了程序代码的阅读完整性,还是贴了出来,代码如下(示例):
public class Node<T extends Comparable<T>> {
T data;
Node<T> leftChild;
Node<T> rightChild;
public Node(T data) {
this(data,null,null);
}
public Node(T data, Node<T> leftChild, Node<T> rightChild) {
this.data = data;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
2.建立完全二叉树
1.先来看一张图,方便理解数组转换成完全二叉树创建的过程。
**解释:从上面的图我们看到顶上蓝色的就是完全二叉树,而图片靠下部的列表就是生成完全二叉树的数据源,每次当前数据的index都是父类传过来的index,当我们第一次调用的时候肯定index = 0,然后开始遍历,左孩子的index等于它的父节点的 index * 2 + 1 ,右孩子的index就是等于它的父节点的 index * 2 + 2。也就是我们看到图片中我写了一个绿色的公式,这里说的index就是我们去数据源拿数据的位置,然后经过递归之后,完全二叉数就完成了创建。 **
下面附上完全二叉树的代码
/**
* 完全二叉树
* @author yong.su
*
* @param <T>
*/
public class CompleteTree<T extends Comparable<T>> {
//根节点
Node<T> root;
/**
* 通过数组来创建完全二叉树
* @param arr 源数据
*/
public void create(T[] arr) {
root = createCompleteTree(arr,0);
}
/*
* 中序遍历
*/
public void midOrder() throws Exception {
if(root == null) throw new Exception("root is null!");
midOrder(root);
System.out.println();
}
/*
* 先序遍历
*/
public void preOrder() throws Exception {
if(root == null) throw new Exception("root is null!");
preOrder(root);
System.out.println();
}
/*
* 计算深度
*/
public int caculateDepth() throws Exception {
if(root == null) throw new Exception("root is null!");
return caculateDepth(root);
}
/*
* 找到对应的节点
*/
public Node<T> findNode(T data) throws Exception {
if(root == null) throw new Exception("root is null!");
return findNode(data,root);
}
/*
* 找到对应的节点的父节点
*/
public Node<T> findNodeParent(T data) throws Exception{
if(root == null) throw new Exception("root is null!");
return findNodeParent(root,data);
}
/**
* 创建完全二叉树
* @param arr 源数据
* @param index 当前索引值
* @return 创建好的节点
*/
private Node<T> createCompleteTree(T[] arr, int index) {
Node<T> newNode = null;
//保证index不会越界
if(index < arr.length){
newNode = new Node<T>(arr[index]);
newNode.leftChild = createCompleteTree(arr, 2 * index + 1);
newNode.rightChild = createCompleteTree(arr, 2 * index + 2);
}
return newNode;
}
/**
* 中序遍历
* @param node
*/
private void midOrder(Node<T> node) {
if(node == null) return;
midOrder(node.leftChild);
System.out.print(node.data + " ");
midOrder(node.rightChild);
}
/**
* 先序遍历
* @param node
*/
private void preOrder(Node<T> node) {
if(node == null) return;
System.out.print(node.data + " ");
midOrder(node.leftChild);
midOrder(node.rightChild);
}
/**
* 计算深度
* @param node 根节点
* @return 深度
*/
private int caculateDepth(Node<T> node) {
int leftDepth,rightDepth;
if(node == null) return 0;
else {
leftDepth = caculateDepth(node.leftChild);
rightDepth = caculateDepth(node.rightChild);
if(leftDepth >= rightDepth) {
return leftDepth+1;
}else {
return rightDepth+1;
}
}
}
/**
* 找到对应的节点
* 这里与二叉搜索树的查找方式是不一样的。
* @param data 查找的元素
* @param root 根节点
* @return 返回对应的节点否则为null
*/
private Node<T> findNode(T data,Node<T> root) {
if (root == null){
return null;
}
Node<T> treeNode = null;
if(root.leftChild != null) {
treeNode = findNode(data,root.leftChild);
if(treeNode != null) return treeNode;
}
int compareResult = data.compareTo(root.data);
if(compareResult == 0) return root;
if(root.rightChild !=null) {
treeNode = findNode(data,root.rightChild);
if(treeNode != null) return treeNode;
}
return treeNode;
}
/**
* 找到对应的节点的父节点
* @param root 根节点
* @param data 查找的元素
* @return 对应的节点的父节点否则返回null
*/
private Node<T> findNodeParent(Node<T> root, T data){
int compareResult1 = root.leftChild.data.compareTo(data);
int compareResult2 = root.rightChild.data.compareTo(data);
if(root == null ||compareResult1 == 0 || compareResult2 == 0)
return root;
Node<T> left = findNodeParent(root.leftChild,data);
if(left != null) return left;
Node<T> right = findNodeParent(root.rightChild,data);
if(right != null) return right;
return left;
}
}
3.调用与测试
下面就是调用的过程以及运行结果:
public static void main(String[] args) throws Exception{
CompleteTree<Integer> tree = new CompleteTree<Integer>();
Integer arr[] = {3, 56, 23, 78, 12, 67, 100, 2};
tree.create(arr);
tree.preOrder();
System.out.println(tree.caculateDepth());
System.out.println(tree.findNode(2).data);
System.out.println(tree.findNodeParent(12).data);
}
运行结果:
PS:纯属个人理解,希望指正!