二叉树
定义
二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。
二叉树的递归定义为:
二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树 。
二叉树性质
性质1:二叉树的第i层上至多有2i-1(i≥1)个节点 。
性质2:深度为h的二叉树中至多含有2h-1个节点 。
性质3:若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1。
性质4:具有n个节点的满二叉树深为log2n+1。
性质5:若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
当i=1时,该节点为根,它无双亲节点。
当i>1时,该节点的双亲节点的编号为i/2 。
若2i≤n,则有编号为2i的左节点,否则没有左节点。
若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点 。
实现
顺序存储
public class ArrayBinaryTree<T> {
private Object[] arr; // 用数组来存储树的所有节点
private int deep; // 保存该树的深度
private int size; // 数组大小
private static final int DEFAULT_DEEP = 5; // 树的默认深度
/**
* 以默认的深度来创建二叉树
*/
public ArrayBinaryTree() {
this.deep = DEFAULT_DEEP;
this.size = (int) Math.pow(2, deep) - 1; // Math.pow(2,deep)返回第一个参数的第二个参数次幂的值
arr = new Object[size];
}
/**
* 以指定深度来创建二叉树
* @param deep
*/
public ArrayBinaryTree(int deep) {
this.deep = deep;
this.size = (int) Math.pow(2, deep) - 1;
arr = new Object[size];
}
/**
* 以指定深度,指定根节点创建二叉树
*
* @param deep 树的深度
* @param data 数据
*/
public ArrayBinaryTree(int deep, T data) {
this.deep = deep;
this.size = (int) Math.pow(2, deep) - 1;
arr = new Object[size];
arr[0] = data; // 根节点
}
/**
* 为指定节点添加子节点。
*
* @param index 需要添加子节点的父节点的索引
* @param data 新子节点的数据
* @param left 是否为左节点
*/
public void add(int index, T data, boolean left) {
if (arr[index] == null) {
throw new RuntimeException(index + "处节点为空,无法添加子节点");
}
if (2 * index + 1 >= size) {
throw new IndexOutOfBoundsException();
}
if (left) {
arr[2 * index + 1] = data; // 添加左子节点
} else {
arr[2 * index + 2] = data; // 添加右子结点
}
}
/**
* 判断二叉树是否为空
* @return
*/
public boolean isEmpty() {
return arr[0] == null; // 根据根元素来判断二叉树是否为空
}
/**
* 返回根节点
* @return
*/
@SuppressWarnings("unchecked")
public T getRoot() {
return (T) arr[0];
}
/**
* 返回指定节点(非根节点)的父节点
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public T getParent(int index) {
return (T) arr[(index - 1) / 2];
}
/**
* 返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public T getLeft(int index) {
if (2 * index + 1 >= size) {
throw new RuntimeException("该节点为叶子节点,无子节点");
}
return (T) arr[index * 2 + 1];
}
/**
* 返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public T getRight(int index) {
if (2 * index + 1 >= size) {
throw new RuntimeException("该节点为叶子节点,无子节点");
}
return (T) arr[index * 2 + 2];
}
/**
* 返回该二叉树的深度。
* @param index
* @return
*/
public int getDeep(int index) {
return deep;
}
/**
* 返回指定节点的位置。
* @param data
* @return
*/
public int index(T data) {
for (int i = 0; i < size; i++) { // 该循环实际上就是按广度遍历来搜索每个节点
if (arr[i].equals(data)) {
return i;
}
}
return -1;
}
/**
* 打印数组
*/
public String toString() {
return Arrays.toString(arr);
}
/**
* 测试方法
* @param args
*/
public static void main(String[] args) {
ArrayBinaryTree<String> binTree = new ArrayBinaryTree<String>(4, "根结点");
binTree.add(0, "第二层右子节点", false); // 第一个参数为需要添加子节点的父节点的索引: 即根节点
binTree.add(2, "第三层右子节点", false);
binTree.add(6, "第四层右子节点", false);
System.out.println(binTree);
}
}
链式存储
class TreeNode {
private int key = 0;
private String data = null;
private boolean isVisted = false;
private TreeNode leftChild = null;
private TreeNode rightChild = null;
public TreeNode() {
}
public TreeNode(int key, String data) {
this.key = key;
this.data = data;
this.leftChild = null;
this.rightChild = null;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public TreeNode getLeftChild() {
return leftChild;
}
public void setLeftChild(TreeNode leftChild) {
this.leftChild = leftChild;
}
public TreeNode getRightChild() {
return rightChild;
}
public void setRightChild(TreeNode rightChild) {
this.rightChild = rightChild;
}
public boolean isVisted() {
return isVisted;
}
public void setVisted(boolean isVisted) {
this.isVisted = isVisted;
}
}
public class BinaryTree {
private TreeNode root = null;
public BinaryTree() {
root = new TreeNode(1, "rootNode(A)");
}
public void createBinTree(TreeNode root) {
// 手动的创建(结构如图所示)
TreeNode newNodeB = new TreeNode(2, "B");
TreeNode newNodeC = new TreeNode(3, "C");
TreeNode newNodeD = new TreeNode(4, "D");
TreeNode newNodeE = new TreeNode(5, "E");
TreeNode newNodeF = new TreeNode(6, "F");
root.setLeftChild(newNodeB);
root.setRightChild(newNodeC);
root.getLeftChild().setLeftChild(newNodeD);
root.getLeftChild().setRightChild(newNodeE);
root.getRightChild().setRightChild(newNodeF);
}
public boolean IsEmpty() {
// 判二叉树空否
return root == null;
}
public int Height() {
// 求树高度
return Height(root);
}
public int Height(TreeNode subTree) {
if (subTree == null)
return 0; // 递归结束:空树高度为0
else {
int i = Height(subTree.getLeftChild());
int j = Height(subTree.getRightChild());
return (i < j) ? j + 1 : i + 1;
}
}
public int Size() {
// 求结点数
return Size(root);
}
public int Size(TreeNode subTree) {
if (subTree == null)
return 0;
else {
return 1 + Size(subTree.getLeftChild())
+ Size(subTree.getRightChild());
}
}
public TreeNode Parent(TreeNode element) {
// 返回双亲结点
return (root == null || root == element) ? null : Parent(root, element);
}
public TreeNode Parent(TreeNode subTree, TreeNode element) {
if (subTree == null)
return null;
if (subTree.getLeftChild() == element
|| subTree.getRightChild() == element)
// 找到, 返回父结点地址
return subTree;
TreeNode p;
// 先在左子树中找,如果左子树中没有找到,才到右子树去找
if ((p = Parent(subTree.getLeftChild(), element)) != null)
// 递归在左子树中搜索
return p;
else
// 递归在左子树中搜索
return Parent(subTree.getRightChild(), element);
}
public TreeNode LeftChild(TreeNode element) {
// 返回左子树
return (element != null) ? element.getLeftChild() : null;
}
public TreeNode RightChild(TreeNode element) {
// 返回右子树
return (element != null) ? element.getRightChild() : null;
}
public TreeNode getRoot() {
// 取得根结点
return root;
}
public void destroy(TreeNode subTree) {
// 私有函数: 删除根为subTree的子树
if (subTree != null) {
destroy(subTree.getLeftChild()); // 删除左子树
destroy(subTree.getRightChild()); // 删除右子树
// delete subTree; //删除根结点
subTree = null;
}
}
public void Traverse(TreeNode subTree) {
System.out.println("key:" + subTree.getKey() + "--name:"
+ subTree.getData());
Traverse(subTree.getLeftChild());
Traverse(subTree.getRightChild());
}
public void PreOrder(TreeNode subTree) {
// 先根
if (subTree != null) {
visted(subTree);
PreOrder(subTree.getLeftChild());
PreOrder(subTree.getRightChild());
}
}
public void InOrder(TreeNode subTree) {
// 中根
if (subTree != null) {
InOrder(subTree.getLeftChild());
visted(subTree);
InOrder(subTree.getRightChild());
}
}
public void PostOrder(TreeNode subTree) {
// 后根
if (subTree != null) {
PostOrder(subTree.getLeftChild());
PostOrder(subTree.getRightChild());
visted(subTree);
}
}
public void LevelOrder(TreeNode subTree) {
// 水平遍边
}
public boolean Insert(TreeNode element) {
// 插入
return true;
}
public boolean Find(TreeNode element) {
// 查找
return true;
}
public void visted(TreeNode subTree) {
subTree.setVisted(true);
System.out.println("key:" + subTree.getKey() + "--name:"
+ subTree.getData());
}
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.createBinTree(bt.root);
System.out.println("the size of the tree is " + bt.Size());
System.out.println("the height of the tree is " + bt.Height());
System.out.println("*******先根(前序)[ABDECF]遍历*****************");
bt.PreOrder(bt.root);
System.out.println("*******中根(中序)[DBEACF]遍历*****************");
bt.InOrder(bt.root);
System.out.println("*******后根(后序)[DEBFCA]遍历*****************");
bt.PostOrder(bt.root);
}
}
Last updated