树:
1.子树不能相交
2.除了根节点,每个节点有且仅有一个父节点
3.一颗N个节点的树有N-1条边
树的概念
节点的度:一个节点含有子树的个数
树的度:一棵树中,所有 节点的度 中最大的值
叶子节点(终端节点):度为0的节点(没有孩子)
节点层次:从根节点为第1层
树的高度/深度:节点的最大层次
二叉树
1.不存在度大于2的节点
2.左右有序
以下的都为二叉树:
二叉树的分类:
1.满二叉树:每层的节点数达到最大值
如果二叉树层数为K,这棵树的节点总数为(2^K - 1)
2.完全二叉树:从上到下,从左到右,依次存放不间断。
二叉树的性质:
1.若规定根节点层数为1,则一颗非空二叉树第i层上最多有2^(i-1)个节点。(最多就是每个节点都有两个孩子)
2.若规定只有根节点的二叉树的深度为1,则深度为K的二叉树的最大节点数为2^k-1。(这里的最大就是当二叉树为满二叉树的时候)
3.对于任何一颗二叉树,叶子节点个数 = 度为2的节点数 + 1。
4.具有n个节点的完全二叉树的深度为 log(n+1) 向上取整。
5.具有n个节点的完全二叉树
1)已知父亲节点的下标为i,求孩子节点的下标。
左孩子:(2i)+ 1
右孩子:(2i)+ 2
2)已知孩子节点下标为i,求父亲节点
父亲节点:(i-1)/ 2
二叉树的存储:顺序和链式
常见的链式表示有二叉和三叉表示法
//孩子表示法
class Node{
int val;//数值域
Node left;//左孩子 代表以左孩子为根节点的整个左子树
Node right;//右孩子 代表以右孩子为根节点的整个右子树
}
//孩子双亲表示法
class Node{
int val;//数值域
Node left;//左孩子 代表以左孩子为根节点的整个左子树
Node right;//右孩子 代表以右孩子为根节点的整个右子树
Node parent;//当前节点的根节点(父亲节点)
}
二叉树的遍历
//前序遍历---递归
public void preOrder(TreeNode root){
if(root == null) return;
//当无左孩子后返回根节点
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
//中序遍历
public void inOrder(TreeNode root){
if(root == null) return;
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
//后序遍历
public void postOrder(TreeNode root){
if(root == null) return;
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val + " ");
}
二叉树的基本操作:
//1.获取树中结点的个数
public int size = 0;
public int nodeSize(TreeNode root) {//用各种遍历方式都可以
if(root == null) return 0;
size++;//根
nodeSize(root.left);//左
nodeSize(root.right);//右
return size;
}
public int nodeSize2(TreeNode root) {
if(root == null) return 0;
return nodeSize2(root.left) + nodeSize2(root.right) + 1;
}
//2.求叶子节点的个数
public int leafSize = 0;
public void getLeafSize(TreeNode root) {
if(root == null) return;//空树
if(root.left == null && root.right == null){
leafSize++;
}
getLeafSize(root.left);
getLeafSize(root.right);
}
public int getLeafSize2(TreeNode root) {//用子问题去求
if(root == null) return 0;
if(root.left == null && root.right == null){
return 1;
}
return getLeafSize2(root.left) + getLeafSize2(root.right);
}
//3.获取第k层结点的个数
public int getKLevelNodeCount(TreeNode root, int k) {
if(root == null) return 0;
if(k == 1) {
return 1;
}
return getKLevelNodeCount(root.left, k-1)+
getKLevelNodeCount(root.right, k-1);
}
//4.求树的高度
public int height = 0;
public int getHeight(TreeNode root) {
//整棵树的高度 = max (左树的高度,右树的高度)+ 1
if(root == null) return 0;
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
return (leftHeight > rightHeight) ? leftHeight+1:rightHeight+1;
}
//5.寻找指定的节点
public boolean findNode(TreeNode root, char key){
if(root == null) return false;
if(root.val == key) {//判断根节点的值是否等于key
return true;
}
boolean leftVal = findNode(root.left,key);
if(leftVal == true) {
return true;//左边找到了就不用去右边找了
}
boolean rightVal = findNode(root.right,key);
if(rightVal == true) {
return true;//右边找到了
}
return false;
}
//6.层序遍历
public void levelOrder(TreeNode root) {
if(root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()) {
TreeNode cur = queue.poll();
System.out.print(cur.val + " ");
if(cur.left != null) {
queue.offer(cur.left);
}
if(cur.right != null) {
queue.offer(cur.right);
}
}
}
public List<List<TreeNode>> levelOrder1(TreeNode root) {
List<List<TreeNode>> ret = new ArrayList<>();
if(root == null) {
return ret;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);//根节点入队列
while(!queue.isEmpty()) {//队列空则结束
//求一下当前队列的大小 4
int size = queue.size();
List<TreeNode> tmp = new ArrayList<>();
while(size != 0) {
//出队列四次,相当于把这一层的节点都出队了
TreeNode cur = queue.poll();//cur等于弹出的元素
tmp.add(cur);
size--;
if(cur.left != null) {
queue.offer(cur.left);
}
if(cur.right != null) {
queue.offer(cur.right);
}
}
ret.add(tmp);
}
return ret;
}
//7.是否为完全二叉树
public boolean isCompleteTree(TreeNode root) {
if(root == null) {
return true; //空树也是完全二叉树
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()) {
TreeNode cur = queue.poll();
if(cur == null) {//当cur遇到null时就停下
break;
}
queue.offer(cur.left);//此时就不需要考虑是否为空
queue.offer(cur.right);
}
while(!queue.isEmpty()) {
TreeNode tmp = queue.poll();
if(tmp != null) {//队列若有不是null的节点则不是完全二叉树;反之则是
return false;
}
}
return true;
}