public class Node {
Object value; //结点值
Node leftChild;//左子树的引用
Node rightChild;//右子树的引用
public Node() {
}
public Node(Object value) {
this.value = value;
}
public Node(Object value, Node leftChild, Node rightChild) {
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
@Override
public String toString() {
return “Node{” +
“value=” + value +
“, leftChild=” + leftChild +
“, rightChild=” + rightChild +
‘}’;
}
}
二叉树接口
package btree;
/**
- 二叉树接口
- @author Administrator
/
public interface BinaryTree {
/*
* 是否空树
* @return
/
public boolean isEmpty();
/*
* 树结点数量
* @return
*/
public int size();
/**
* 获取二叉树的高度
* @return
/
public int getHeight();
/*
* 查询指定值的结点
* @param value
* @return
/
public Node findKey(Object value); // 查找
/*
* 前序递归遍历
/
public void preOrderTraverse();
/*
* 中序遍历递归操作
/
public void inOrderTraverse();
/*
* 后序遍历递归操作
/
public void postOrderTraverse();
/*
* 中序遍历非递归操作
/
public void inOrderByStack();
/*
* 前序遍历非递归操作
/
public void preOrderByStack();
/*
* 后序遍历非递归操作
*/
public void postOrderByStack();
/**
* 按照层次遍历二叉树
*/
public void levelOrderByStack();
}
二叉树实现类
package btree;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
- @author lijing
- @date 2019-03-29-10:35
- @discroption 二叉树实现类
*/
public class LinkedBinaryTree implements BinaryTree {
private Node root;//根节点
public LinkedBinaryTree(Node root) {
this.root = root;
}
public LinkedBinaryTree() {
}
@Override
public boolean isEmpty() {
//根结点为空说明二叉树为空
return root == null;
}
@Override
public int size() {
return this.getSize(this.root);
}
private int getSize(Node root) {
if (root == null) {
//递归结束条件:根结点为空(这里的根结点是每次访问时的根节点,并不是this.root)
return 0;
} else {
//先得到左子树的元素个数
int nl = this.getSize(root.leftChild);
//在得到右子树的元素个数
int nr = this.getSize(root.rightChild);
//将左子树和右子树的元素个数相加,再加上根结点
return nl + nr + 1;
}
}
@Override
public int getHeight() {
return this.getHeight(this.root);
}
private int getHeight(Node root) {
if (root == null) {
//递归结束条件:根结点为空
return 0;
} else {
//先得到左子树的高度
int nl = this.getHeight(root.leftChild);
//再得到右子树的高度
int nr = this.getHeight(root.rightChild);
//取左右子树中高度比较大的一个,再加上根结点
return nl > nr ? nl + 1 : nr + 1;
}
}
@Override
public Node findKey(Object value) {
return findKey(this.root, value);
}
private Node findKey(Node root, Object value) {
if (root == null) {
//如果root为空,就直接返回null(递归结束条件)
return null;
} else if (root.value.equals(value)) {
//如果找到value就返回root结点(递归结束条件)
return root;
} else {
//否则就分别查找左子树和右子树
Node lkey = findKey(root.leftChild, value);
Node rkey = findKey(root.rightChild, value);
//如果lkey非空就返回lkey,否则就返回rkey,(包含lkey和rkey都为空的情况,返回null)
return lkey != null ? lkey : rkey;
}
}
@Override
public void preOrderTraverse() {
System.out.print(“前序遍历:”);
this.preOrderTraverse(this.root);
System.out.println();
}
//前序遍历 根左右
private void preOrderTraverse(Node root) {
if (root != null) {
//递归结束条件:根结点为空
//遍历顺序:先输出元素,再遍历左右子树
System.out.print(root.value + " ");
this.preOrderTraverse(root.leftChild);
this.preOrderTraverse(root.rightChild);
}
}
@Override
public void inOrderTraverse() {
System.out.print(“中序遍历:”);
this.inOrderTraverse(this.root);
System.out.println();
}
//中序遍历 左根右
private void inOrderTraverse(Node root) {
if (root != null) {
//递归结束条件:根结点为空
//遍历顺序:先遍历左子树,再打印元素,再遍历右子树
this.inOrderTraverse(root.leftChild);
System.out.print(root.value + " ");
this.inOrderTraverse(root.rightChild);
}
}
@Override
public void postOrderTraverse() {
System.out.print(“后序遍历:”);
this.postOrderTraverse(this.root);
System.out.println();
}
private void postOrderTraverse(Node root) {
if (root != null) {
//递归结束条件:根结点为空
//遍历顺序:先遍历左右右子树,再打印元素
this.postOrderTraverse(root.leftChild);
this.postOrderTraverse(root.rightChild);
System.out.print(root.value + " ");
}
}
@Override
public void inOrderByStack() {
System.out.print(“非递归中序遍历:”);
//创建栈
Deque stack = new LinkedList<>();
Node current = this.root;
while (current != null || !stack.isEmpty()) {
//将根结点以及每棵子树的根结点放入栈中,直到遇到一颗没有左孩子的子树为止
while (current != null) {
stack.push(current);
current = current.leftChild;
}
//判断如果栈不空,就将栈顶元素取出(此时栈顶元素一定是没有左孩子的)
//打印结点,然后将当前结点指向右孩子
if (!stack.isEmpty()) {
current = stack.pop();
System.out.print(current.value + " ");
current = current.rightChild;
}
}
System.out.println();
}
@Override
public void preOrderByStack() {
System.out.print(“非递归前序遍历:”);
//创建栈
Deque stack = new LinkedList<>();
Node current = this.root;
while (current != null || !stack.isEmpty()) {
//先输出根结点的值,再将结点放入栈中,知道放入结点的右孩子为空
while (current != null) {
System.out.print(current.value + " ");
stack.push(current);
current = current.leftChild;
}
// 如果栈不空,就让当前结点指向右孩子,经过上面的操作之后,栈顶元素一定是没有左孩子并且被打印过的,
// 所以只需要处理右孩子即可,如果右孩子不为空则会在下一轮操作中入栈。
if (!stack.isEmpty()) {
current = stack.pop().rightChild;
}
}
System.out.println();
}
@Override
public void postOrderByStack() {
System.out.print(“非递归后序遍历:”);
//创建栈
Deque stack = new LinkedList<>();
Node current = this.root;//当前结点
Node last = null;//指向当前结点的上一个
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
current = current.leftChild;
}
current = stack.peek();//取栈顶元素
if (current.rightChild == null || current.rightChild == last) {
//如果没有右孩子或者右孩子被访问过,就访问该结点
Node node = stack.pop();
System.out.print(node.value + " ");
last = current;
current = null;
} else {
//把当前结点设为当前结点的右孩子
current = current.rightChild;
}
}
System.out.println();
}
@Override
public void levelOrderByStack() {
System.out.print(“层次遍历:”);
//创建队列
Queue queue = new LinkedList<>();
if (root != null) {
queue.add(this.root);
}
while (!queue.isEmpty()) {
//如果队列非空,就取出队列顶部元素,并将左右孩子入队
Node node = queue.poll();
System.out.print(node.value + " ");
if (node.leftChild != null) {
queue.add(node.leftChild);
}
if (node.rightChild != null) {
queue.add(node.rightChild);
}
}
System.out.println();
}
}
}