递归实现完全二叉树


一、二叉完全树是什么?

完全二叉树是由满二叉树而引出来的,若设二叉树的深度为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:纯属个人理解,希望指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值