二叉树【Java算法(八)】
写在前面的话:
- 参考资料:《漫画算法》79页 、数据结构课堂上C语言代码
- 本章内容:二叉树基础知识,较为简单,请放心食用
- IDE:IntelliJ IDEA 2021.2.1
- JDK:Java8
目录
项目结构:
树是由一个或多个结点组成的有限集合。
- 必有一个特定的称为根(ROOT)的结点;
- 剩下的结点被分成n>=0个互不相交的集合T1、T2、......Tn,而且,这些集合的每一个
又都是树。树T1、T2、......Tn被称作根的子树(Subtree)。
二叉树,其结点有左右子树之分,二叉树基本上有以下这些情况:
- 空二叉树
- 只有1个根节点的二叉树
- 只有左子树
- 只有右子树
- 完全二叉树
- 满二叉树
二叉树包含完全二叉树和满二叉树两种特殊形式
1.存储方式
存储方式一般有两种:数组或链式存储
1.1 数组
二叉树用数组存储,应该将空节点设置成null,如下图。
1.2 链式存储
遍历方式:
- 前序遍历:根左右
- 中序遍历:左根右
- 后序遍历:左右根
- 层次遍历:遍历完一层,才遍历下一层
2.代码实战
代码构建的二叉树:
构建二叉树的方式很多,这里主要提两个。
2.1 把线性的链表转换成非线性的二叉树
BinaryTree.java
package ex01;
/*
二叉树
*/
import java.util.LinkedList;
public class BinaryTree<E> {
/*
二叉树节点
*/
public static class TreeNode<E>{
E data;//节点保存的数据
TreeNode<E> leftChild;//左孩子
TreeNode<E> rightChild;//右孩子
TreeNode(E data){
this.data = data;
}
}
/**
* 创建一颗二叉树
* @param list 输入序列
* @return 返回一棵树
*/
public <E> TreeNode createBinaryTree(LinkedList<E> list){
//创建节点
TreeNode<E> treeNode = null;
//判断输入序列list是否等于null,或者输入序列list为空
if(list == null || list.isEmpty()){
return null;
}
//获取list第一个数据
E data = list.removeFirst();
//当获取到的是null时,跳过下面语句
if(data != null){
//创建一颗二叉树有很多种方式
// 1.前序遍历创建二叉树
// 2.中序遍历创建二叉树
// 3.后序遍历创建二叉树
// ...
//这里采用前序遍历的方式创建二叉树
treeNode = new TreeNode<>(data);
treeNode.leftChild = createBinaryTree(list);
treeNode.rightChild = createBinaryTree(list);
}
return treeNode;
}
/**
* 前序遍历:根左右
* @param treeNode 传入一个根节点
*/
public void formerSequenceTraversal(TreeNode<E> treeNode){
if(treeNode == null){
//如果节点为空
return;
}
System.out.print(treeNode.data + " ");
formerSequenceTraversal(treeNode.leftChild);
formerSequenceTraversal(treeNode.rightChild);
}
/**
* 中序遍历:左根右
* @param treeNode 传入一个根节点
*/
public void inTheSequenceTraversal(TreeNode<E> treeNode){
if(treeNode == null){
//如果节点为空
return;
}
inTheSequenceTraversal(treeNode.leftChild);
System.out.print(treeNode.data + " ");
inTheSequenceTraversal(treeNode.rightChild);
}
/**
* 后序遍历:左右根
* @param treeNode 传入一个根节点
*/
public void afterTheSequenceTraversal(TreeNode<E> treeNode){
if(treeNode == null){
//如果节点为空
return ;
}
afterTheSequenceTraversal(treeNode.leftChild);
afterTheSequenceTraversal(treeNode.rightChild);
System.out.print(treeNode.data + " ");
}
}
测试类:TestTree.java
package ex01;
/*
测试二叉树
*/
import java.util.Arrays;
import java.util.LinkedList;
public class TestTree {
public static void main(String[] args) {
//按照前序遍历,填充内容
Integer[] array = new Integer[]{1,2,4,null,null,5,null,null,3,null,6};
//将数据添加进list当中
LinkedList<Integer> list = new LinkedList<>(Arrays.asList(array));
BinaryTree<Integer> binaryTree = new BinaryTree<>();
//创建二叉树
BinaryTree.TreeNode root = binaryTree.createBinaryTree(list);
//前序遍历
System.out.println("前序遍历:");
binaryTree.formerSequenceTraversal(root);
//中序遍历
System.out.println("\n中序遍历:");
binaryTree.inTheSequenceTraversal(root);
//后序遍历
System.out.println("\n后序遍历:");
binaryTree.afterTheSequenceTraversal(root);
}
}
测试截图:
2.2 通过获取节点,一步步构建二叉树
二叉树:BinaryTree.java
package ex02;
public class BinaryTree {
/*
二叉树节点
*/
public class Node{
Integer data;
Node lChild;
Node rChild;
Node(Integer data){
this.data = data;
}
}
/**
* 创建二叉树节点
* @param data 节点中的数据
* @return 返回一个二叉树节点
*/
public Node getNode(Integer data){
//创建一个节点
Node node = new Node(data);
return node;
}
/**
* 创建二叉树
* @return 返回根节点
*/
public Node getTree(){
/*
思路:
1.要创建一个二叉树,肯定要有节点 ==> 第一步就是获取节点
2.二叉树不是一个个孤立的节点 ==> 第二部建立联系
3.返回第一个节点(根节点)
*/
//1.获取节点
Node node1 = getNode(1);
Node node2 = getNode(2);
Node node3 = getNode(3);
Node node4 = getNode(4);
Node node5 = getNode(5);
Node node6 = getNode(6);
//2.建立联系
node1.lChild = node2;
node1.rChild = node3;
node2.lChild = node4;
node2.rChild = node5;
node3.rChild = node6;
//3.返回根节点
return node1;
}
/**
* 前序遍历:根左右
* @param root 传入根节点
*/
public void formerSequenceTraversal(Node root){
if(root == null){
//如果节点为空
return;
}
System.out.print(root.data + " ");
formerSequenceTraversal(root.lChild);
formerSequenceTraversal(root.rChild);
}
/**
* 中序遍历:左根右
* @param root 传入根节点
*/
public void inTheSequenceTraversal(Node root){
if(root == null){
//如果节点为空
return;
}
inTheSequenceTraversal(root.lChild);
System.out.print(root.data + " ");
inTheSequenceTraversal(root.rChild);
}
/**
* 后序遍历:左右根
* @param root 传入根节点
*/
public void afterTheSequenceTraversal(Node root){
if(root == null){
//如果节点为空
return;
}
afterTheSequenceTraversal(root.lChild);
afterTheSequenceTraversal(root.rChild);
System.out.print(root.data + " ");
}
}
测试类:TestTree.java
package ex02;
public class TestTree {
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree();
BinaryTree.Node root = binaryTree.getTree();
System.out.println("前序遍历:");
binaryTree.formerSequenceTraversal(root);
System.out.println("\n中序遍历:");
binaryTree.inTheSequenceTraversal(root);
System.out.println("\n后序遍历:");
binaryTree.afterTheSequenceTraversal(root);
}
}
测试截图:与方法一相同,证明结果正确
完