数据结构---二叉树(4)

二叉树相关问题集:

1. 求二叉树中的节点个数

 

2. 求二叉树的深度
3. 前序遍历,中序遍历,后序遍历
4. 分层遍历二叉树(按层次从上往下,从左往右)
5. 将二叉查找树变为有序的双向链表
6. 求二叉树第K层的节点个数
7. 求二叉树中叶子节点的个数
8. 判断两棵二叉树是否结构相同
9. 判断二叉树是不是平衡二叉树
10. 求二叉树的镜像
11. 求二叉树中两个节点的最低公共祖先节点
12. 求二叉树中节点的最大距离
13. 由前序遍历序列和中序遍历序列重建二叉树

 

14.判断二叉树是不是完全二叉树

 

部分题目解析:

 

	// 结点类
	static class Node {
		int value; // 该节点存储的值。
		Node leftChild; // 指向左子节点的引用。
		Node rightChild; // 指向右子节点的引用。

		Node(int value) {
			this.value = value;
			leftChild = null;
			rightChild = null;
		}
	}

	private Node root; // 根节点

	

	// 用数组构建二叉树
	public void createBinTree(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			root = insert(root, arr[i]);
		}
	}

	// 向二叉树中插入节点(构建二叉排序树)
	public Node insert(Node node, int value) {
		if (node == null) {
			node = new Node(value);
		} else {
			if (value <= node.value) {
				node.leftChild = insert(node.leftChild, value);
			} else {
				node.rightChild = insert(node.rightChild, value);
			}
		}
		return node;
	}

	// 1. 求二叉树中的节点个数
	// 递归解法:
	// (1)如果二叉树为空,节点个数为0
	// (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
	public int GetNodeNum(Node root) {
		if (root == null) // 递归出口
			return 0;
		return GetNodeNum(root.rightChild) + GetNodeNum(root.leftChild) + 1;
	};

	// 2. 求二叉树的深度
	// 递归解法:
	// (1)如果二叉树为空,二叉树的深度为0
	// (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
	public int GetDepth(Node root) {
		if (root == null) // 递归出口
			return 0;
		int depthLeft = GetDepth(root.leftChild);
		int depthRight = GetDepth(root.rightChild);
		return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);
	};

	// 5. 求二叉树第K层的节点个数
	// 递归解法:
	// (1)如果二叉树为空或者k<1返回0
	// (2)如果二叉树不为空并且k==1,返回1
	// (3)如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
	int GetNodeNumKthLevel(Node root, int k) {
		if (root == null || k < 1)
			return 0;
		if (k == 1)
			return 1;
		int numLeft = GetNodeNumKthLevel(root.leftChild, k - 1); // 左子树中k-1层的节点个数
		int numRight = GetNodeNumKthLevel(root.rightChild, k - 1); // 右子树中k-1层的节点个数
		return (numLeft + numRight);
	}

    //非递归算法
    int getKthLevelNodesTotal(Node pRoot, int k ){
        if( pRoot == NULL )
            return 0;
     
        LinqueQueue <Node>  que = new LinqueQueue<>();
        que.enqueue( pRoot );
        int curLevelNodesTotal = 0;
        int curLevel = 0;
   
        while( !que.isEmpty() ){
            ++curLevel;//当前层数
            curLevelNodesTotal = que.size();
            if( curLevel == k )//如果层数等于给定层数
                break;
 
            int cntNode = 0;
            while( cntNode < curLevelNodesTotal){//将下一层节点入队
                ++cntNode;
                pRoot = que.peek();
                que.dequeue();
                if( pRoot.left != NULL )
                    que.enqueue(pRoot.left);
                if( pRoot.right != NULL )
                    que.enqueue( pRoot.right);
        }
       }
    
        while ( !que.isEmpty() )
            que.dequeue();
 
        if( curLevel == k )
            return curLevelNodesTotal;
        return 0;  //如果k大于树的深度
   }


	// 6. 求二叉树中叶子节点的个数
	// 递归解法:
	// (1)如果二叉树为空,返回0
	// (2)如果二叉树不为空且左右子树为空,返回1
	// (3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
	int GetLeafNodeNum(Node root) {
		if (root == null)
			return 0;
		if (root.leftChild == null && root.rightChild == null)
			return 1;
		int numLeft = GetLeafNodeNum(root.leftChild); // 左子树中叶节点的个数
		int numRight = GetLeafNodeNum(root.leftChild); // 右子树中叶节点的个数
		return (numLeft + numRight);
	}
    

	// 8. 判断二叉树是不是平衡二叉树
	// 递归解法:
	// (1)如果二叉树为空,返回真
	// (2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假
	boolean IsAVL(Node root) {
		if (root == null) // 空树,返回真
			return true;

		// 调用了求高度的方法
		int left = GetDepth(root.leftChild);
		int right = GetDepth(root.rightChild);

		int diff = left - right;
		if (diff < -1 || diff > 1)
			return false;

		return IsAVL(root.leftChild) && IsAVL(root.rightChild);

	}


11、题目:树中两个节点的最低公共祖先。
思路一: 输入两个树节点,求他们的最低公共祖先,
——如果是二叉树,而且是二叉搜索树,那么是可以找到公共节点的。
二叉搜索树都是排序过的,位于左子树的节点都比父节点小,而位于右子树上面的节点都比父节点大。
如果当前节点的值比两个结点 的值都大,那么最低的共同的父节点一定是在当前节点的左子树中,于是下一步遍历当前节点的左子节点。
如果当前节点的值比两个结点的值都小,那么最低的共同的父节点一定是在当前节点的右子树中,于是下一步遍历当前节点的右子节点。
这样从上到下,找到的第一个在两个输入结点的值之间的节点,就是最低的公共祖先。

 


思路二:
如果这棵树不是二叉搜索树,甚至连二叉树都不是,而只是普通的树。
——如果有指向父节点的指针,那么这个题目转换成了求,两个双向链表的第一个公共结点的问题。

思路三:
这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。
——遍历这个树,看以这个节点为根的子树是否包含这两个节点,如果包含,判断这个节点的子节点是否包含,
——知道子节点都不包含而这个当前的节点包含,那么这个节点就是最低的公共祖先。

 

思路四:
这棵树是普通的树,而且这个树中的结点没有指向父节点的指针。
——用两个链表分别保存从根节点到输入的两个结点的路径,然后把问题转换成两个链表的最后公共节点。

 

	//从跟到某结点的路径
	public static boolean printPath(Node root,int target,Stack<Node> s)
	{
	     if (root == null)
	         return false;
	 
	     if (root.value == target || printPath(root.leftChild,target,s) || printPath(root.rightChild,target,s))
	     {
	          s.push(root);   //路径上的结点标识打印出来
	          return true;
	     }
	 
	     return false;
	}

 

 


参考来源:

java实现二叉树相关代码-----数据结构

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值