二叉树代码

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();
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值