二叉树在图论中的定义为, 二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,左右节点的定义是逻辑上。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。
本文中分别用递归和非递归的方式实现对二叉树的广度与深度遍历;
1 . 构建一颗二叉树, 可以指定树上的总节点数
树节点定义
static class Tree {
private Integer number;//node number
private String name;// node name
private Tree left;// left subTree
private Tree right;//right subTree
public Tree() {
}
public Tree(int number) {
this.number = number;
}
public Integer getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Tree getLeft() {
return left;
}
public void setLeft(Tree left) {
this.left = left;
}
public Tree getRight() {
return right;
}
public void setRight(Tree right) {
this.right = right;
}
/**
* Build binary-tree Recursive
*
* @param node
* @param data
*/
public void buildTree(Tree node, int data) {
if (node.number == null) {
node.setNumber(data);
} else if (data < node.number) {
if (node.left == null) {
node.left = new Tree(data);
} else {
buildTree(node.left, data);
}
} else {
if (node.right == null) {
node.right = new Tree(data);
} else {
buildTree(node.right, data);
}
}
}
}
构造生成二叉树
private static Set<Integer> buildNUmberSet(int count) {
Set<Integer> numbers = new HashSet<>(count);
int max = count * 10 + 1;
Random random = new Random();
while (numbers.size() < count) {
numbers.add(random.nextInt(max));
}
return numbers;
}
/**
* Create one binary tree with tree nodes number
*
* @param nodeNum
*/
public static Tree createBinaryTree(int nodeNum) {
Set<Integer> numbers = buildNUmberSet(nodeNum);
Iterator<Integer> iterator = numbers.iterator();
Tree tree = new Tree();
while (iterator.hasNext()) {
tree.buildTree(tree, iterator.next());
}
return tree;
}
2 . 广度非递归遍历
public static void breadthSearchNotRecursive(Tree tree){
if (tree == null) return;
Deque<Tree> treeQueue = new ArrayDeque();
treeQueue.addLast(tree);
while (!treeQueue.isEmpty()){
tree = treeQueue.poll();
logger.error("Tree number is: {}", tree.getNumber());
if (tree.getLeft() != null){
treeQueue.add(tree.getLeft());
}
if (tree.getRight() != null){
treeQueue.add(tree.getRight());
}
}
}
3 . 深度递归遍历
public static void depthSearchRecursive(Tree tree){
if (tree == null) return;
logger.error("Tree number is: {}", tree.getNumber());
if (tree.getLeft() != null)
depthSearchRecursive(tree.getLeft());
if (tree.getRight() != null)
depthSearchRecursive(tree.getRight());
}
4 . 深度非递归遍历
public static void depthSearchNotRecursive(Tree tree){
if (tree == null) return;
Stack<Tree> treeStack = new Stack<>();
treeStack.add(tree);
while (!treeStack.isEmpty()){
tree = treeStack.pop();
logger.error("Tree number is: {}", tree.getNumber());
if (tree.getRight() != null){
treeStack.push(tree.getRight());
}
if (tree.getLeft() != null){
treeStack.push(tree.getLeft());
}
}
}
5 . 最后单元测试
@Test
public void BreadthSearchRecursive () {
Tree tree = createBinaryTree(50);
logger.error("==============================================");
//广度非递归遍历二叉树
breadthSearchNotRecursive(tree);
}
@Test
public void DepthSearchRecursive () {
Tree tree = createBinaryTree(50);
//深度递归遍历二叉树
depthSearchRecursive(tree);
logger.error("**********************************************");
//深度非递归遍历二叉树
depthSearchNotRecursive(tree);
}
注释: 二叉树的深度优先遍历从递归的角度去分析, 是比较好理解的, 文章中途由于惯性思维想以递归的方式去实现二叉树的广度遍历, 没有尝试出来,嘿嘿!