前言
上一篇文章讲了 java 二叉树的实现以及前序、中序、后续遍历实现 ,本文将讲述使用java实现二叉搜索树,以及二叉搜索树的前序、中序、后续遍历实现。
二叉搜索树
二叉搜索树,又被称为二叉查找树。具有以下特点:
- 节点的左子树仅包含键小于节点键的节点。
- 节点的右子树只包含键大于节点键的节点。
- 左右子树也必须是二叉搜索树。
简单来说就是左孩子比父节点小,右孩子比父节点大,二叉搜索树还有一个特性就是”中序遍历“可以让结点有序。
二叉搜索树实现代码
import java.util.ArrayList;
import java.util.List;
public class BinarySearchTree {
/**
* 二叉搜索树总的节点数
*/
private int size;
/**
* 根节点
*/
public Node root;
public class Node {
public int value;
private Node leftNode;
private Node rightNode;
private Node(int value, Node leftNode, Node rightNode) {
this.value = value;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
/**
* 获取二叉搜索树的总节点数
*/
public int size() {
return size;
}
/**
* 向二叉搜索树中增加节点
*/
public void add(int addValue) {
if (null == root) {
root = new Node(addValue, null, null);
} else {
add(addValue, root);
}
size++;
}
private void add(int addValue, Node node) {
if (null != node) {
int value = node.value;
if (addValue < value) {
if (null != node.leftNode) {
add(addValue, node.leftNode);
} else {
node.leftNode = new Node(addValue, null, null);
}
}
if (addValue >= value) {
if (null != node.rightNode) {
add(addValue, node.rightNode);
} else {
node.rightNode = new Node(addValue, null, null);
}
}
}
}
/**
* 前序遍历
*/
public List<Integer> preTraverse() {
return preTraverse(new ArrayList<>(), root);
}
private List<Integer> preTraverse(List<Integer> 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<Integer> midTraverse() {
return midTraverse(new ArrayList<>(), root);
}
private List<Integer> midTraverse(List<Integer> 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<Integer> afterTraverse() {
return afterTraverse(new ArrayList<>(), root);
}
private List<Integer> afterTraverse(List<Integer> 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<Integer> levelsTraverse() {
return levelsTraverse(new ArrayList<>(), root);
}
private List<Integer> levelsTraverse(List<Integer> 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() {
size = 0;
root = null;
}
}
测试
public static void main(String[] args) throws UnsupportedEncodingException {
//新建一个二叉树并向其中插入数据
BinarySearchTree binaryTree = new BinarySearchTree();
binaryTree.add(8);
binaryTree.add(3);
binaryTree.add(10);
binaryTree.add(1);
binaryTree.add(6);
binaryTree.add(14);
binaryTree.add(4);
binaryTree.add(7);
binaryTree.add(13);
//输出根节点的值
BinarySearchTree.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();
}
输出
8
9
[8, 3, 1, 6, 4, 7, 10, 14, 13]
[1, 3, 4, 6, 7, 8, 10, 13, 14]
[1, 4, 7, 6, 3, 13, 14, 10, 8]
[8, 3, 10, 1, 6, 14, 4, 7, 13]
二叉搜索树的缺点
试着把 1、2、3、4、5、6、7、8、9、10 这几个数字依次加入到二叉搜索树中你会发现,它是这样的
是一个不平衡的二叉搜索树,假如要获取10这个节点需要耗费的时间很长。
所以就有了另一种平衡二叉搜索树来解决不平衡的问题,关于平衡二叉搜索树可以看下我的另一篇文章:java 自平衡二叉搜索树的实现以及前序、中序、后续遍历实现