目录
1. 树
-
1.1 树的概念与结构
树是一种非线性的数据结构,由n(n>=0)个有限结点组成一个具有层次关系的集合。
- 一棵有N个结点的树有N-1条边
- 每个节点可有0或多个子结点
- 每一个非根结点有且只有一个父结点
- 相关定义
- 根结点:没有父结点的结点
- 叶结点:没有子结点的结点
- 兄弟结点:具有形同父结点的结点
- 结点的度:一个节点含有的子树的个数
- 树的度:树中最大的结点的度
- 树的高度/深度:树种结点的最大层次
- 森林:由m(m>=0)棵不相交的树的集合
-
1.2 树的表示
可以使用链表表示,每个结点都保存值、该结点的第一个孩子结点以及同一层的下一个兄弟节点。
采用链式存储。
2. 二叉树
-
2.1 概念
二叉树要么为空,要么是只有两棵称为左子树和右子树的二叉树的树。
- 特点
- 二叉树中每个结点最多有两棵子树
- 二叉树是有序树
-
2.2 二叉树的5种结构
- 空树
- 没有任何子树的二叉树
- 只有左子树的二叉树
- 只有右子树的二叉树
- 既有左子树又有右子树的二叉树
-
2.3 特殊的二叉树
- 满二叉树
- 每一层的结点数都达到最大值的二叉树
- K层的二叉树,有(2^k)-1个结点
- 是一种特殊的完全二叉树,满二叉树一定是完全二叉树,而完全二叉树不一定是满二叉树
- 完全二叉树
- 在满二叉树的基础上,从后依次删除结点
- 满二叉树
-
2.4 二叉树的存储结构
- 顺序结构存储
- 使用数组来存储,只适合表示完全二叉树(否则会有空间浪费)
- 链式结构存储
- 用链表来表示一棵二叉树,每个结点都包含数据以及左右指针3部分。
- 顺序结构存储
-
2.5 链式结构的实现
/**
* 树
* Author:qqy
*/
public class Tree {
private static class Node {
char value;
//左子树
Node left;
//右子树
Node right;
Node(char v) {
this.value = v;
}
}
// 当树是空树,node = null;
/**
* 求二叉树结点的个数
*
* @param root
*/
private static int count = 0;
//遍历思想:定义一个变量用于计数,然后后序遍历
private static void countByTraversal(Node root) {
if (root != null) {
countByTraversal(root.left);
countByTraversal(root.right);
count++;
}
}
//递归思想:总的结点个数=左子树结点个数+右子树结点个数+1
//终止条件:空树 0;一个子结点的树 1(可选)
private static int count(Node root) {
if (root == null) {
return 0;
} else {
int left = count(root.left);
int right = count(root.right);
return left + right + 1;
}
}
/**
* 求二叉树叶子节点的个数
* 递归思想:总的叶结点个数=左子树叶结点个数+右子树叶节点个数
* 终止条件:空树 0;没有左子树与右子树 1
*
* @param root
* @return
*/
private static int leafCount(Node root) {
if(root==null){
return 0;
}
if(root.left==null&&root.right==null){
return 1;
}
return leafCount(root.left)+leafCount(root.right);
}
/**
* 二叉树的高度
* 递归思想:二叉树的高度=左子树的高度与右子树的高度的最大值+1
* 终止条件:空树的高度为0
*
* @param root
* @return
*/
private static int height(Node root) {
if(root==null){
return 0;
}
return (height(root.left)>height(root.right)?height(root.left):height(root.right))+1;
//优化
// return java.lang.Math.max(height(root.left),height(root.right))+1;
}
/**
* 第k层的结点数
* 递归思想:根结点的第k层的结点数=根结点左子树的第k-1层的结点数+根结点右子树的第k-1层的结点数
* 终止条件:空树 0;第1层 1
*
* @param root
* @param k
* @return
*/
private static int kLevel(Node root, int k) {
if(root==null){
return 0;
}
if(k==1){
return 1;
}
return kLevel(root.left,k-1)+kLevel(root.right,k-1);
}
/**
* 在二叉树中查找一个值,找到,返回结点;未找到,返回null
* 递归思想:先查看根结点,没有则查看左子树,还没有查看右子树
* 终止条件:根结点等于给定值,返回根结点
* @param root
* @param v
* @return
*/
private static Node find(Node root, char v) {
if(root==null){
return null;
}
if(root.value==v){
return root;
}
Node r=find(root.left,v);
if(r!=null){
return r;
}
//根结点和左子树都没有,不论右子树中有没有都返回查找右子树的返回值
return find(root.right,v);
}
}