目录
1.树的概念
树是一种非线性的数据结构,由n个有限节点组成了一个具有层次关系的集合。当n为0时,该树表示一棵空树。
2.重要名词
结点的度与树的度:树中一个结点的的子树的个数成为该结点的度。树中各结点的最大值为树的度。
分支结点和叶子结点:度不为零的结点称为非终端结点,也叫分支结点。度为零的结点称为终端结点或者叶子结点。
孩子结点、双亲结点和兄弟结点: 在一棵树中,每个结点的后继,被称作该结点的孩子结点(或子女结点)。该结点也被称为孩子结点的双亲结点。具有同一个双亲的孩子结点则为兄弟结点。
结点的层次和树的高度: 根节点的层次为第一层,以此类推。树的结点的最大层次称为树的最大深度。
路径与路径长度:路径长度等于路径所通过的结点数目减1
3.树的性质
性质1: 树的结点数等于所有结点的度数之和+1
每个结点指向N个结点,加上root的一个
性质2: 度为m的树中第i层至多有
性质3: 高度为h的m次树至多有: 个结点。(通过等比数列之和计算得到)
性质4:具有n个结点的m次树的最小高度为
4.二叉树
4.1 概念
一颗树上所有结点的度均不大于2,则这棵树是一颗二叉树,空树是一颗特殊的二叉树。
4.2 两种储存表示方法
//孩子表示法
class Node{
int val;
Node left;
Node right;
}
//孩子双亲表示法
class Node{
int val;
Node left;
Node right;
Node parent;
}
4.3 特殊的二叉树
满二叉树:在一颗二叉树中,除了叶子结点之外,其他所有结点的度均为2,则该二叉树为满二叉树。
完全二叉树:从根节点开始,非空结点按照从上到下,从左到右依次递增,。
4.4 二叉树的重要性质
性质1:非空二叉树上叶结点数等于双分支结点数加1
性质2: 第i层最多有个结点
性质3:高度为h的二叉树最多有个结点
性质4: 具有n个结点的完全二叉树的深度为向上取整
性质5:对于具有n个结点的完全二叉树,分层从1开始编号,
一个结点的序号为j,则它的双亲编号为j/2,从0开始则双亲结点的编号为 [(j-1)/2].
若编号为j的结点有左孩子结点,则左孩子编号为2j;若编号为j的结点有右孩子结点,则右孩子编号为2j+1.从0开始则左右孩子分别为2j+1和2j+2
5.二叉树的遍历
class BTNode{
public char val;
public BTNode left;
public BTNode right;
public BTNode(char val){
this.val=val;
}
}
创造一颗简单的树
public class BinaryTree {
/*public BTNode root;*/
public BTNode creatTree(){
BTNode A=new BTNode('A');
BTNode B=new BTNode('B');
BTNode C=new BTNode('C');
BTNode D=new BTNode('D');
BTNode E=new BTNode('E');
BTNode F=new BTNode('F');
BTNode G=new BTNode('G');
BTNode H=new BTNode('H');
A.left=B;
A.right=C;
B.left=D;
B.right=E;
C.left=F;
C.right=G;
E.right=H;
return A;
}
5.1 前序遍历
//前序遍历
//—访问根结点--->根的左子树--->根的右子树
public void preOrder(BTNode root){//递归思想遍历
if(root==null){
return;
}
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
//非递归的遍历方式
public List<Integer> inorder2(BTNode root){
List<Integer> ret=new ArrayList<>();
if(root==null){
return ret;
}
//new一个栈来存储遍历的元素
Stack<BTNode> stack=new Stack<>();
//让cur从根节点开始去遍历元素
BTNode cur=root;
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
//开始遍历的为根节点处元素
stack.push(cur);
//前序遍历遍历顺序为--根节点-左-右
ret.add(cur.val);
//将左树一直遍历直至null
cur=cur.left;
}
//这时栈中存储的是每一个左树根节点,从最下方根节点开始
//一一去遍历每个顶部元素的右结点,当栈为空且cur也为空时遍历完成
BTNode top=stack.pop();
cur=top.right;
}
return ret;
}
5.2中序遍历
//中序遍历
public void inorder(BTNode root){
if(root==null){
return;
}
inorder(root.left);
System.out.println(root.val+" ");
inorder(root.right);
}
5.3后序遍历
//后续遍历
//树的左子树--右子树--根节点
void postorder(BTNode root){
if(root==null){
return;
}
postorder(root.left);
postorder(root.right);
System.out.print(root.val+" ");
}
5.4 分层遍历
//二叉树的分层遍历//层序遍历
public void levelOrder(BTNode root){
Queue<BTNode> queue=new LinkedList<>();
if(root==null){
return;
}
queue.offer(root);
while (!queue.isEmpty()){
BTNode cur=queue.poll();
System.out.println(cur.val);
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
}
6.关于二叉树较重要的题
6.1寻找最近公共祖先(超重要)
public BTNode lowestCommonAncestor(BTNode root,BTNode p,BTNode q){
//当根结点为null时,向上返回空
if(root==null){
return root;
}
if(root==p||root==q){
return root;
}
//左树搜索的结果
BTNode leftsearch=lowestCommonAncestor(root.left, p, q);
//右树搜索的结果
BTNode rightsearch=lowestCommonAncestor(root.right, p, q);
if(leftsearch!=null&&rightsearch!=null){
return root;
}else if(leftsearch!=null){
return leftsearch;
}else{
return rightsearch;
}
}
设p和q分别为7和4
如上图所示,从根节点3出发,root不为null且不为p或q,则进入leftSearch,5不为null,也不为p或q,继续向下进行leftsearch,6也不为null,不为p或q。继续左递归发现root为null,返回值为6的根节点,进入rightsearch,右节点也为null。返回上一个根节点5,这时候节点5的左树搜索方法结束,进入右树搜索。对于右树,2不是null或p、q节点,向下递归左树右树,左为p,右为q,分别向上返回7和4,这时2的左搜索和右搜索都不为null,因而根据下面的if 语句,将根节点2返回给上一级即根节点5,对于根节点5,左搜索为null,右搜索为2,则返回不为null的右搜索给节点3,对于节点3的右搜索为null,因而根据if语句最终最近公共祖先为左树返回的结果即2。
6.2 其他重点题,未完待续。。。。