1. 树型结构(了解)
二叉树问题解题i思路
利用递归的思路,将问题拆分为子问题(拆分为左数+右树的子问题)
1.1 概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看
起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
有一个特殊的节点,称为根节点,根节点没有前驱节点
除根节点外,其余节点被分成M(M > 0)个互不相交的集合T1、T2、…、Tm,其中每一个集合 Ti (1 <= i
<= m) 又是一棵与树类似的子树。每棵子树的根节点有且只有一个前驱,可以有0个或多个后继
树是递归定义的。
1.2 概念(重要)
节点的度:一个节点含有的子树的个数称为该节点的度;
树的度:一棵树中,最大的节点的度称为树的度;
**双亲节点或父节点:**若一个节点含有子节点,则这个节点称为其子节点的父节点;
**孩子节点或子节点:**一个节点含有的子树的根节点称为该节点的子节点;
**根结点:**一棵树中,没有双亲结点的结点;
**节点的层次:**从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
**树的高度或深度:**树中节点的最大层次;
树的以下概念只需了解,在看书时只要知道是什么意思即可:
非终端节点或分支节点:度不为0的节点;
**兄弟节点:**具有相同父节点的节点互称为兄弟节点;
**堂兄弟节点:**双亲在同一层的节点互为堂兄弟;
**节点的祖先:**从根到该节点所经分支上的所有节点;祖先
**子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
森林:**由m(m>=0)棵互不相交的树的集合称为森林
二叉树的设计与实现
二叉树的实现
public class MyBinaryTree {
public static class Node {
private char val;
private Node left;
private Node right;
public Node(char val) {
this.val = val;
}
}
public Node buildATree(){
Node nodeA = new Node('A');
Node nodeB = new Node('B');
Node nodeC = new Node('C');
Node nodeD = new Node('D');
Node nodeE = new Node('E');
Node nodeF = new Node('F');
Node nodeG = new Node('G');
Node nodeH = new Node('H');
nodeA.left = nodeB;
nodeA.right = nodeC;
nodeB.left = nodeD;
nodeB.right = nodeE;
nodeE.left = nodeG;
nodeG.right = nodeH;
nodeC.left = nodeF;
return nodeA;
}
二叉树的遍历
- NLR:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点—>根的左子树—>根的右子树。
- LNR:中序遍历(Inorder Traversal)——根的左子树—>根节点—>根的右子树。
- LRN:后序遍历(Postorder Traversal)——根的左子树—>根的右子树—>根节点。
先序遍历
/**
* 先序遍历
* 传入一个个根节点根据先序遍历该节点
* 根左右
* @param root
*/
public void preOrder(Node root){
if (root == null ){
return;
}
//根节点
System.out.print(root.val + " ");
//左子数
preOrder(root.left);
//右字数
preOrder(root.right);
}
中序遍历
/**
* 中序遍历
* 左根右
* @param root
*/
public void inOrder( Node root ){
if (root == null){
return;
}
inOrder(root.left);
System.out.print(root.val+ " ");
inOrder(root.right);
}
后序遍历
/**
* 后序遍历
* 左右根
* @param root
*/
public void postOrder(Node root) {
if ( root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
计算二叉树的节点个数
/**
* 传入一个二叉树的根节点,求出该二叉树的节点个数
* @param root 二叉树的根节点
* @return 节点的个数
*/
public int getNodeCount(Node root){
if (root == null){
return 0;
}
return 1+getNodeCount(root.left)+getNodeCount(root.right);
}
求二叉树叶子节点的个数
/**
* 传入一个二叉树根节点root,就能求得该二叉树的叶子节点个数
* @param root
* @return
*/
public int getLeafNodeCount( Node root){
if ( root == null){
return 0;
}
if (root.left == null && root.right == null){
return 1;
}
return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
}
求该树的高度
/**
* 传入一个根节点root,就能求得该树高度
* @param root
* @return
*/
public int height( Node root ){
if (root == null){
return 0;
}
return 1 + Math.max(height(root.left), height(root.right));
}
求第K层节点的个数
/**
* 传入一个二叉树的根节点root,求出第k层节点个数
* @param root
* @return
*/
public int getKLevelNodes(Node root , int k){
if (root == null){
return 0 ;
}
if (k == 1){
return 1;
}
return getKLevelNodes(root.left , k-1) + getKLevelNodes(root.right , k-1);
}
源代码
import java.sql.SQLOutput;
public class MyBinaryTree {
public static class Node {
private char val;
private Node left;
private Node right;
public Node(char val) {
this.val = val;
}
}
public Node buildATree(){
Node nodeA = new Node('A');
Node nodeB = new Node('B');
Node nodeC = new Node('C');
Node nodeD = new Node('D');
Node nodeE = new Node('E');
Node nodeF = new Node('F');
Node nodeG = new Node('G');
Node nodeH = new Node('H');
nodeA.left = nodeB;
nodeA.right = nodeC;
nodeB.left = nodeD;
nodeB.right = nodeE;
nodeE.left = nodeG;
nodeG.right = nodeH;
nodeC.left = nodeF;
return nodeA;
}
/**
* 先序遍历
* 传入一个个根节点根据先序遍历该节点
* 根左右
* @param root
*/
public void preOrder(Node root){
if (root == null ){
return;
}
//根节点
System.out.print(root.val + " ");
//左子数
preOrder(root.left);
//右字数
preOrder(root.right);
}
/**
* 中序遍历
* 左根右
* @param root
*/
public void inOrder( Node root ){
if (root == null){
return;
}
inOrder(root.left);
System.out.print(root.val+ " ");
inOrder(root.right);
}
/**
* 后序遍历
* 左右根
* @param root
*/
public void postOrder(Node root) {
if ( root == null){
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
/**
* 传入一个二叉树的根节点,求出该二叉树的节点个数
* @param root 二叉树的根节点
* @return 节点的个数
*/
public int getNodeCount(Node root){
if (root == null){
return 0;
}
return 1+getNodeCount(root.left)+getNodeCount(root.right);
}
/**
* 传入一个二叉树根节点root,就能求得该二叉树的叶子节点个数
* @param root
* @return
*/
public int getLeafNodeCount( Node root){
if ( root == null){
return 0;
}
if (root.left == null && root.right == null){
return 1;
}
return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
}
/**
* 传入一个根节点root,就能求得该树高度
* @param root
* @return
*/
public int height( Node root ){
if (root == null){
return 0;
}
return 1 + Math.max(height(root.left), height(root.right));
}
/**
* 判断一颗以root为根节点的二叉树中是否包含值为val的节点
* @param root
* @return
*/
public boolean contins(Node root ,char val){
if ( root == null){
return false;
}
if (root.val == val){
return true;
}
return contins(root.left , val) || contins(root.right ,val);
}
/**
* 传入一个二叉树的根节点root,求出第k层节点个数
* @param root
* @return
*/
public int getKLevelNodes(Node root , int k){
if (root == null){
return 0 ;
}
if (k == 1){
return 1;
}
return getKLevelNodes(root.left , k-1) + getKLevelNodes(root.right , k-1);
}
public static void main(String[] args){
MyBinaryTree myBinaryTree = new MyBinaryTree();
Node root = myBinaryTree.buildATree();
System.out.print("先序遍历结果为:");
myBinaryTree.preOrder(root);
System.out.println();
System.out.print("中序遍历结果为:");
myBinaryTree.inOrder(root);
System.out.println();
System.out.print("后序遍历:");
myBinaryTree.postOrder(root);
System.out.println();
System.out.print("节点个数为");
myBinaryTree.getNodeCount(root);
System.out.print("叶子节点个数: ");
System.out.println(myBinaryTree.getLeafNodeCount(root));
System.out.print("该数的高度为: ");
System.out.println(myBinaryTree.height(root));
System.out.print("否包含值为H的节点: ");
System.out.println(myBinaryTree.contins(root, 'H'));
System.out.print("否包含值为T的节点: ");
System.out.println(myBinaryTree.contins(root, 'T'));
System.out.print("二叉树第4层节点个数: ");
System.out.println(myBinaryTree.getKLevelNodes(root,4));
System.out.print("二叉树第3层节点个数: ");
System.out.println(myBinaryTree.getKLevelNodes(root,3));
}
}