前言
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。
本文主要讲的是二叉树中的完全二叉树的实现,
完全二叉树
一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
简单来说每个节点按照从上往下,从左往右的顺序添加并且每个节点最多只有左右两个节点,就是完全二叉树。
完全二叉树实现代码
简单说明,插入时运用队列来记住插入顺序;遍历时采用递归来遍历。
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class BinaryTree<T> {
/**
* 二叉树总的节点数
*/
private int size;
/**
* 根节点
*/
public Node root;
/**
* 记录插入的队列
*/
private Queue<Node> queue;
public class Node {
public T value;
private Node leftNode;
private Node rightNode;
private Node(T value, Node leftNode, Node rightNode) {
this.value = value;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
/**
* 获取二叉树的总节点数
*/
public int size() {
return size;
}
/**
* 向二叉树中增加节点
*/
public void add(T addValue) {
Node node = new Node(addValue, null, null);
if (null == root) {
root = node;
queue = new LinkedList<>();
queue.offer(node);
} else {
Node queNode = queue.peek();
if (null == queNode.leftNode) {
queNode.leftNode = node;
queue.offer(queNode.leftNode);
} else if (null == queNode.rightNode) {
queNode.rightNode = node;
queue.poll();
queue.offer(queNode.rightNode);
}
}
size++;
}
/**
* 前序遍历
*/
public List<T> preTraverse() {
return preTraverse(new ArrayList<>(), root);
}
private List<T> preTraverse(List<T> list, Node node) {
if (list.size() != size && null != node) {
list.add(node.value);
//遍历左节点
preTraverse(list, node.leftNode);
//遍历右节点
preTraverse(list, node.rightNode);
}
return list;
}
/**
* 中序遍历
*/
public List<T> midTraverse() {
return midTraverse(new ArrayList<>(), root);
}
private List<T> midTraverse(List<T> list, Node node) {
if (list.size() != size && null != node) {
//遍历左节点
midTraverse(list, node.leftNode);
list.add(node.value);
//遍历右节点
midTraverse(list, node.rightNode);
}
return list;
}
/**
* 后序遍历
*/
public List<T> afterTraverse() {
return afterTraverse(new ArrayList<>(), root);
}
private List<T> afterTraverse(List<T> list, Node node) {
if (list.size() != size && null != node) {
//遍历左节点
afterTraverse(list, node.leftNode);
//遍历右节点
afterTraverse(list, node.rightNode);
list.add(node.value);
}
return list;
}
/**
* 层序遍历
*/
public List<T> levelsTraverse() {
return levelsTraverse(new ArrayList<>(), root);
}
private List<T> levelsTraverse(List<T> list, Node root) {
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
while (list.size() != size) {
Node node = queue.poll();
list.add(node.value);
if (node.leftNode != null) {
queue.offer(node.leftNode);
}
if (node.rightNode != null) {
queue.offer(node.rightNode);
}
}
return list;
}
/**
* 清空二叉树
*/
public void clear() {
queue = null;
size = 0;
root = null;
}
}
测试
public class Main {
public static void main(String[] args) {
//新建一个二叉树并向其中插入数据
BinaryTree<String> binaryTree = new BinaryTree<>();
binaryTree.add("A");
binaryTree.add("B");
binaryTree.add("C");
binaryTree.add("D");
binaryTree.add("E");
binaryTree.add("F");
binaryTree.add("G");
binaryTree.add("H");
binaryTree.add("i");
binaryTree.add("j");
binaryTree.add("k");
binaryTree.add("L");
binaryTree.add("M");
binaryTree.add("N");
binaryTree.add("O");
//输出根节点的值
BinaryTree.Node root = binaryTree.root;
System.out.println(root.value);
//输出二叉树总的节点数
System.out.println(binaryTree.size());
//前序遍历
System.out.println(binaryTree.preTraverse());
//中序遍历
System.out.println(binaryTree.midTraverse());
//后序遍历
System.out.println(binaryTree.afterTraverse());
//层序遍历
System.out.println(binaryTree.levelsTraverse());
//清空二叉树
binaryTree.clear();
}
}
输出
A
15
[A, B, D, H, i, E, j, k, C, F, L, M, G, N, O]
[H, D, i, B, j, E, k, A, L, F, M, C, N, G, O]
[H, i, D, j, k, E, B, L, M, F, N, O, G, C, A]
[A, B, C, D, E, F, G, H, i, j, k, L, M, N, O]
本文主要讲了java 二叉树的实现以及前序、中序、后续遍历实现,但现实中二叉搜索树却更比较实用,比如用在数据库索引和文件索引的设计中,所以下一篇文章介绍下 java 二叉搜索树的实现以及前序、中序、后续遍历实现
参考:
b+树详解
Linked complete binary tree & its creation
Construct a complete binary tree from given array in level order fashion
完全二叉树插入器
Implementing a Binary Tree in Java