二叉树相关问题集:
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;
}
参考来源: