一、二叉树概述
1、简介:
在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree),次序不能颠倒。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。
2、基本形态:
二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:(1) 空二叉树——(a);
(2) 只有一个根结点的二叉树——(b);
(3) 只有左子树——(c);
(4) 只有右子树——(d);
(5) 完全二叉树——(e)
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。3、重要概念:
(1) 完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2) 满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
(3) 深度——二叉树的层数,就是深度。
4、性质:
(1) 在非空二叉树中,第i层的结点总数不超过, i>=1;
(2) 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为log2 n +1 。
二、代码实现
import java.util.LinkedList;
/*
* ①用Java代码模拟实现一个二叉树结构
* ②创建该二叉树
* ③遍历该二叉树。
*/
public class TreeTest {
public static void main(String[] args)throws Exception {
int[] arr={4,8,6,9,5,2,7,1,3};
//使用数组构建二叉树
BinaryTree tree=new BinaryTree(arr);
//遍历二叉树
//tree.preOrderTraverse();//先序遍历
//tree.inOrderTraverse();//中序遍历
//tree.postOrderTraverse();//后序遍历
tree.levelTraverse();//按层次遍历
}
}
//自定义二叉树类
class BinaryTree{
//根节点成员变量
private Node root;
//无参构造方法
public BinaryTree(){
root=null;
}
//使用一个数组来构造二叉树
public BinaryTree(int[] arr){
for (int i:arr) {
root=insertNode(root,i);
}
}
/*插入节点,并且根据节点的值来判断插入方向。
当值小于或等于当前节点的值,则插入当前节点的左侧;
否则,插入当前节点的右侧。
每次从根节点开始递归比较。*/
private Node insertNode(Node node,int value){
if(node==null)
node=new Node(value);
else{
if(value <= node.getValue())
node.setLeft(insertNode(node.getLeft(),value));
else
node.setRight(insertNode(node.getRight(),value));
}
return node;
}
//遍历二叉树
//先序遍历
public void preOrderTraverse(){
preOrderTraverse1(root);
}
//中序遍历
public void inOrderTraverse(){
inOrderTraverse1(root);
}
//后序遍历
public void postOrderTraverse(){
postOrderTraverse1(root);
}
//按层次遍历
public void levelTraverse(){
levelTraverse1(root);
}
//先序遍历的具体实现
private void preOrderTraverse1(Node node){
if(node!=null){
System.out.println(node.getValue());
preOrderTraverse1(node.getLeft());
preOrderTraverse1(node.getRight());
}
}
//中序遍历的具体实现
private void inOrderTraverse1(Node node){
if(node!=null){
inOrderTraverse1(node.getLeft());
System.out.println(node.getValue());
inOrderTraverse1(node.getRight());
}
}
//后序遍历的具体实现
private void postOrderTraverse1(Node node){
if(node!=null){
postOrderTraverse1(node.getLeft());
postOrderTraverse1(node.getRight());
System.out.println(node.getValue());
}
}
//按层次遍历的具体实现
private void levelTraverse1(Node node){
LinkedList<Node> queue=new LinkedList<Node>();
queue.offerLast(node);
while(!queue.isEmpty()){
Node temp=queue.pollFirst();
if(temp!=null){
System.out.println(temp.getValue());
queue.offerLast(temp.getLeft());
queue.offerLast(temp.getRight());
}
}
}
}
//节点类
class Node{
//每个节点有三个属性:节点值、左子节点、右子节点
private Node left;
private Node right;
private int value;
//无参构造方法
public Node(){}
//通过构造方法初始化节点值
public Node(int value){
this(null,null,value);
}
//通过构造方法初始化节点值、左子节点、右子节点
public Node(Node left,Node right,int value){
this.left=left;
this.right=right;
this.value=value;
}
//获取、设置左子节点
public Node getLeft(){
return left;
}
public void setLeft(Node left){
this.left=left;
}
//获取、设置右子节点
public Node getRight(){
return right;
}
public void setRight(Node right){
this.right=right;
}
//获取、设置节点值
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}