排序二叉树
简介
二叉树的定义,不再介绍;而排序二叉树指的是根据一定排列顺序插入节点组成的一个二叉树;而排列顺序一般指定:小的在左边、大的在右边,数值不重复。
算法实现
主要包含有节点的插入、遍历、查询、删除。
定义节点类
private class Node {
//节点的值
private Integer key;
//左节点
private Node left;
//右节点
private Node right;
public Node() {
super();
}
public Node(Integer key) {
super();
this.key = key;
}
public Integer getKey() {
return key;
}
public Node setKey(Integer key) {
this.key = key;
return this;
}
public Node getLeft() {
return left;
}
public Node setLeft(Node left) {
this.left = left;
return this;
}
public Node getRight() {
return right;
}
public Node setRight(Node right) {
this.right = right;
return this;
}
@Override
public String toString() {
return "Node [key=" + key + ", left=" + left + ", right=" + right + "]";
}
}
插入节点
/**
* 插入节点(封装对外)
* @author Kellan_Song
* @param key 节点值
*/
public static Node insert(Node tree, int key) {
if (tree == null) {
tree = new Node(key);
} else {
insertNode(tree, new Node(key));
}
return tree;
}
/**
* 在排序二叉树中插入节点(内部调用)
* @author Kellan_Song
* @param node 节点树
* @param new_node 新节点
*/
private static void insertNode(Node node, Node new_node) {
//新节点小于父节点,放左边
if (new_node.getKey() < node.getKey()) {
if (node.getLeft() != null) {
insertNode(node.getLeft(), new_node);
} else {
node.setLeft(new_node);
}
}
//新节点大于父节点
if (new_node.getKey() > node.getKey()) {
if (node.getRight() != null) {
insertNode(node.getRight(), new_node);
} else {
node.setRight(new_node);
}
}
}
遍历
二叉树的遍历主要有三种:
- 前序遍历:中间节点优先输出,再输出左节点,最后输出右节点;
- 中序遍历:左节点 - 中间节点 - 右节点
- 后序遍历:左节点 - 右节点 - 中间节点
/**
* 前序遍历:指的是中间节点优先输出
* @author Kellan_Song
* @param node
*/
private static void before_print(Node node) {
if (node != null) {
System.out.print(" " + node.getKey());
before_print(node.getLeft());
before_print(node.getRight());
}
}
/**
* 中序遍历:指的是左节点优先输出后,再输出中间节点,右节点最后输出
* @author Kellan_Song
* @param node
*/
private static void mid_print(Node node) {
if (node != null) {
mid_print(node.getLeft());
System.out.print(" " + node.getKey());
mid_print(node.getRight());
}
}
/**
* 后序遍历:指的是 左节点优先输出,再输出右节点,中间节点最后输出
* @author Kellan_Song
* @param node
*/
private static void after_print(Node node) {
if (node != null) {
after_print(node.getLeft());
after_print(node.getRight());
System.out.print(" " + node.getKey());
}
}
最大值、最小值
/**
* 获取二叉树中最小值
* @author Kellan_Song
* @param tree
* @return
*/
public static Integer minNum(Node tree) {
Node node = lastLeft(tree);
return node == null ? null : node.getKey();
}
/**
* 获取二叉树中最大值
* @author Kellan_Song
* @param tree
* @return
*/
public static Integer maxNum(Node tree) {
Node node = lastRight(tree);
return node == null ? null : node.getKey();
}
/**
* 获取最左节点
* @author Kellan_Song
* @param node
* @return
*/
private static Node lastLeft(Node node) {
return node == null ? null : node.getLeft() != null ? lastLeft(node.getLeft()) : node;
}
/**
* 获取最右节点
* @author Kellan_Song
* @param node
* @return
*/
private static Node lastRight(Node node) {
return node == null ? null : node.getRight() != null ? lastRight(node.getRight()) : node;
}
查询
/**
* 查询是否包含某值
* @author Kellan_Song
* @param node 排序二叉树
* @param n 查询值
* @return
*/
public static boolean contain(Node node, int n) {
if (node == null) return false;
if (node.getKey() < n) {
return contain(node.getRight(), n);
} else if (node.getKey() > n) {
return contain(node.getLeft(), n);
} else {
return true;
}
}
删除节点
删除节点分三种情况:
- 删除节点为叶子节点(无左右节点):直接移除
- 删除节点只有左节点或者只有右节点:则将存在的左节点\右节点指向于删除节点
- 删除节点既有左节点,又有右节点:这种情况比较复杂,无法直接赋值,有两种方式(1)删除目标节点的左节点下的最右节点,并赋值于目标节点;(2)删除目标节点的右节点下的最左节点,并赋值于目标节点。
public static Node removeNode(Node node, int n) {
if (node != null) {
if (node.getKey() < n) {
node.setRight(removeNode(node.getRight(), n));
} else if (node.getKey() > n) {
node.setLeft(removeNode(node.getLeft(), n));
} else {
if (node.getLeft() == null && node.getRight() == null) {
node = null;
} else if (node.getLeft() != null && node.getRight() == null) {
node = node.getLeft();
} else if (node.getLeft() == null && node.getRight() != null) {
node = node.getRight();
} else {
Node node_temp = lastLeft(node.getRight());
node.setRight(removeNode(node.getRight(), node_temp.getKey()));
node.setKey(node_temp.getKey());
}
}
}
return node;
}
验证
public class BTreeTest {
public static void main(String[] args) {
Node root = null;
int arr[] = {8,3,1,6,4,7,10,14,13};
for (int i = 0; i < arr.length; i++) {
root = insert(root, arr[i]);
}
System.out.println("前序遍历:");
before_print(root);
System.out.println("\n中序遍历:");
mid_print(root);
System.out.println("\n后序遍历:");
after_print(root);
System.out.println("\n最小值:" + minNum(root));
System.out.println("最大值:" + maxNum(root));
System.out.println("是否存在3:" + contain(root, 3));
root = removeNode(root, 3);
System.out.println("删除3结果:");
mid_print(root);
}
}
输出结果:
前序遍历:
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
最小值:1
最大值:14
是否存在3:true
删除3结果:
1 4 6 7 8 10 13 14