数据结构
Java实现二叉树
前言
本篇主要介绍二叉树的概念、二叉树的表示、二叉树的操作(三种遍历方式实现、求二叉树的子树、求节点的父节点、二叉树高度…这些方式都是通过递归发方式实现的
//二叉树的数据结构
public class BinaryTreeNode<T> {
private T data;
private BinaryTreeNode<T> leftChild; //左孩子
private BinaryTreeNode<T> rightChild; //右孩子
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public BinaryTreeNode getLeftChild() {
return leftChild;
}
public BinaryTreeNode getRightChild() {
return rightChild;
}
public void setLeftChild(BinaryTreeNode<T> leftChild) {
this.leftChild = leftChild;
}
public void setRightChild(BinaryTreeNode<T> rightChild) {
this.rightChild = rightChild;
}
}
public class BinaryTree<T> {
private BinaryTreeNode<T> root; //根结点
/**
* 初始化二叉树
* @param root
*/
public BinaryTree (BinaryTreeNode<T> root) {
this.root = root;
}
public void setRoot(BinaryTreeNode<T> root) {
this.root = root;
}
public BinaryTreeNode<T> getRoot() {
return root;
}
/**
* 二叉树的清空
* 1.递归遍历清空每个结点
* 2.直接删除树根
*/
public void clear(BinaryTreeNode node) {
if (node != null) {
clear(node.getLeftChild());
clear(node.getRightChild());
node = null; //删除结点
}
}
public void clear() {
clear(root);
}
//判空树
public boolean isEmpty() {
return root == null;
}
/**
* 求二叉树的高度
* 首先要一种获取以某个节点为子树的高度的方法,使用递归调用。
* 如果一个节点为空,那么这个节点肯定是一颗空树,高度为0;
* 如果不为空,那么我们要遍历地比较它的左子树高度和右子树高度,
* 高的一个为这个子树的最大高度然后加上自己本身的高度就是了
* 获取二叉树的高度,只需要调用第一种方法,即传入根节点
*/
public int height() {
return height(root);
}
private int height(BinaryTreeNode<T> node) {
if (node == null) {
return 0;
} else {
//递归获取左子树的高度
int leftHeight = height(node.getLeftChild());
//递归获取右子树的高度
int rightHeight = height(node.getRightChild());
//要算上自身的这一层
return leftHeight > rightHeight ? (leftHeight+1) : (rightHeight+1);
}
}
/**
* 获取二叉树的结点树
* 需要获取以某个节点为根的子树的节点数实现,
* 如果节点为空,则个数肯定为0;如果不为空,
* 则算上这个节点之后,继续递归计算所有子树的节点数,全部相加即可
*/
public int size() {
return size(root);
}
private int size(BinaryTreeNode<T> node) {
if (node == null) {
return 0;
} else {
//要计算本结点,因此需要+1,
return 1+size(node.getLeftChild()) +size(node.getRightChild());
}
}
/**
* 返回左右子树
*/
public BinaryTreeNode<T> getLeftTree(BinaryTreeNode<T> node) {
return node.getLeftChild();
}
public BinaryTreeNode<T> getRightTree(BinaryTreeNode<T> node) {
return node.getRightChild();
}
/**
* 二叉树结点的插入
* 值得指出的是,当这个节点本身有子节点时,这样的插入也会覆盖原来在这个位置上的节点。
* 另外,虽然插入的是子节点,但是子节点也可以代表一颗子树。
* 因为但从这个节点来看并不知道这个节点是否有左右子树存在,所以虽然插入的是一个节点,但有可能
* 插入可很多节点(插入的是一颗子树)
*/
public void insertLeftNode(BinaryTreeNode<T> parent, BinaryTreeNode<T> node) {
parent.setLeftChild(node);
}
public void insertRightNode(BinaryTreeNode<T> parent, BinaryTreeNode<T> node) {
parent.setRightChild(node);
}
/**
* 二叉树的遍历
* 1.先序遍历 (根左右)
* 2.中序遍历 (左根右)
* 3.后序遍历 (左右根)
*/
public void PreOrder(BinaryTreeNode<T> node) {
if (node != null) {
System.out.print(node.getData()+","); //先访问根结点
PreOrder(node.getLeftChild()); //先根遍历左子树
PreOrder(node.getRightChild()); //先根遍历右子树
}
}
public void InOrder(BinaryTreeNode<T> node) {
if (node != null){
PreOrder(node.getLeftChild()); //先根遍历左子树
System.out.print(node.getData()+","); //先访问根结点
PreOrder(node.getRightChild()); //先根遍历右子树
}
}
public void PostOrder(BinaryTreeNode<T> node) {
if (node != null) {
PreOrder(node.getLeftChild()); //先根遍历左子树
PreOrder(node.getRightChild()); //先根遍历右子树
System.out.print(node.getData()+","); //先访问根结点
}
}
public static void main(String[] args) {
BinaryTreeNode<String> nodeA = new BinaryTreeNode<>();
nodeA.setData("A");
BinaryTreeNode<String> nodeB = new BinaryTreeNode<>();
nodeB.setData("B");
nodeA.setLeftChild(nodeB);
BinaryTreeNode<String> nodeC = new BinaryTreeNode<>();
nodeC.setData("C");
nodeA.setRightChild(nodeC);
BinaryTreeNode<String> nodeD = new BinaryTreeNode<>();
nodeD.setData("D");
nodeB.setLeftChild(nodeD);
BinaryTreeNode<String> nodeE = new BinaryTreeNode<>();
nodeE.setData("E");
nodeB.setRightChild(nodeE);
BinaryTreeNode<String> nodeF = new BinaryTreeNode<>();
nodeF.setData("F");
nodeC.setLeftChild(nodeF);
BinaryTreeNode<String> nodeG = new BinaryTreeNode<>();
nodeG.setData("G");
nodeC.setRightChild(nodeG);
BinaryTree<String> tree = new BinaryTree<>(nodeA);
System.out.println("这个树的的高度是: "+tree.height());
System.out.print("先序遍历的结果是: ");
tree.PreOrder(nodeA);
System.out.print("\n"+"中序遍历的结果是: ");
tree.InOrder(nodeA);
System.out.print("\n"+"后序遍历的结果是: ");
tree.PostOrder(nodeA);
}
}