数据结构中的树和前面的线性表有所不同,它属于一种非线性的结构,由N个(N>=0)有限节点组成的具有层次关系的集合,这种结构看起来很像一棵倒挂着的树,也就是树根在上,树叶朝下,所以把它叫做树。
通过观察我们可以发现树这种结构具有以下几个特点:
- 每个节点有0个或多个子节点。
- 非根节点有且只有一个父节点。
- 没有父节点的节点叫做根节点
- 除了整棵树的根节点外,每个子节点又可以分为多个不相交的子树
树的一些概念:
- 一个节点含有的子树的个数就叫做节点的度,如上图A的度就为6
- 一棵树中,最大的节点的度叫做这整棵树的度,如上图这颗树的度就是6
- 度为0的节点叫做叶子节点,或者终端节点,也就是当前这个节点没有子树了,如上图的P,Q等
- 若一个节点含有子节点,则这个节点就叫做它的子节点的父节点或者双亲节点
- 一个节点含有的子树的根节点就叫做该节点的子节点或孩子节点
- 没有父节点的节点叫做根节点
- 从整棵树的根节点开始定义,根节点为第一次,根的子节点为第二层,以此类推。
- 树种节点的最大层次叫做树的高度。
树的表现形式:
class Node {
int val;
Node chid;
Node brother;
其中,val表示当前节点的数据域,child表示当前节点的第一个孩子节点的地址,brother表示当前节点的兄弟节点的地址。
二叉树:
二叉树是一种特殊的树,它的度不能超过2,也就是说这棵树种所有节点的度都不能超过2.
二叉树的表现形式:
class Node {
public int val;//当前节点的数据域
public Node left;//当前节点的左孩子节点
public Node right;//当前节点的右孩子节点
}
二叉树的遍历:
对于这种非线性的数据结构,遍历起来不能一次性直接从0到size(),采取递归进行遍历更为简便。二叉树的遍历方式细分下来有四种:
- 前序遍历:
先访问整棵树的根节点,再递归遍历左子树,再递归遍历右子树。
public static void prev(Node root){
if(root==null){//代表这棵树是空树的时候,也可作为递归的终止条件,当遍历到最后一个叶子节点的时候
return;
}
System.out.println(root.val);//打印当前根节点的数据域
prev(root.left);//然后将当前节点的左子树的根节点又作为方法的参数调用自身
prev(root.right);//再将当前节点的右子树的根节点作为方法的参数调用自身
}
- 中序遍历
先递归遍历左子树,再访问根节点,再递归遍历右子树
public static void prev(Node root){
if(root==null){//代表这棵树是空树的时候,也可作为递归的终止条件,当遍历到最后一个叶子节点的时候
return;
}
prev(root.left);//将当前节点的左子树的根节点作为方法的参数调用自身
System.out.println(root.val);//打印当前根节点的数据域
prev(root.right);//再将当前节点的右子树的根节点作为方法的参数调用自身
}
- 后序遍历
先递归遍历左子树,再递归遍历右子树,最后再访问根节点
public static void prev(Node root){
if(root==null){//代表这棵树是空树的时候,也可作为递归的终止条件,当遍历到最后一个叶子节点的时候
return;
}
prev(root.left);//将当前节点的左子树的根节点又作为方法的参数调用自身
prev(root.right);//当前节点的右子树的根节点作为方法的参数调用自身
System.out.println(root.val);//打印当前根节点的数据域
}
- 层序遍历
对于层序遍历并没有采用递归的方式,并且二叉树的表示法采用的是“孩子兄弟表示法”,借助队列来完成
public static void level(Node root){
Queue<Node> queue = new LinkedList<>();//首先创建一个队列
queue.offer(root);//先将整课树的根节点入队列
while(!queue.isEmpty()){
Node cur = queue.poll();
System.out.println((cur.val));
if(cur.left!=null){
queue.offer(cur.left);//再将左右子树都入队列
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
}