二叉排序树(Java)
二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
定义
一棵空树,或者是具有下列性质的二叉树称为二叉排序树:
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 左、右子树也分别为二叉排序树;
相关操作
举个栗子
以结点权值集合为arr= {3,1,8,9,6,4,7}为例
1.添加结点
- 如果插入结点小于当前结点,则放在左子树
- 如果插入结点大于当前结点,则放在右子树
代码如下
public void add(Node no) {//添加结点
if(no==null) {
return;
}
if(no.data!=this.data) {
if(no.data<this.data) {//如果插入结点小于当前结点,则放在左子树
if(this.left==null) {
this.left=no;
}else {//递归向左子树递归
this.left.add(no);
}
}
if(no.data>this.data) {//如果插入结点大于当前结点,则放在右子树
if(this.right==null) {
this.right=no;
}else {//递归向右子树递归
this.right.add(no);
}
}
}
}
2.查找元素
public void search(int data) {//查找结点
if(data==this.data) {
System.out.printf("查询到%d结点",data);
}else if(data<this.data) {//查找元素小于当前元素,则向左子树递归
if(this.left==null) {
System.out.println("二叉排序树中没有该结点!");
}
this.left.search(data);
}else {//查找元素大于当前结点元素,则向右子树递归
if(this.right==null) {
System.out.println("二叉排序树中没有该结点!");
}
this.right.search(data);
}
}
3.删除结点
主要分为四种情况:
- 如果删除结点是叶子节点
- 如果删除结点只有右子树
- 如果删除结点只有左子树
- 如果删除结点为父结点
以删除父结点8为例:
删除结点同时要保持排序二叉树的性质,所以我们可以让左子树中最大或者右子树中最小的结点替换当前节点,同时将置换结点置空
代码如下
public Node delete(Node root, int key) {//删除结点
if (root == null)
{
return null;
}
if (key < root.getData()){// 向左子树进行删除
root.setLeft(delete(root.getLeft(), key));
return root;
}
if (key > root.getData()){// 向右子树进行删除
root.setRight(delete(root.getRight(), key));
return root;
}
if (root.getLeft() == null && root.getRight() == null){// 如果删除结点是叶子节点
root = null;
return root;
}
if (root.getLeft() == null && root.getRight() != null){// 如果删除结点只有右子树
root = root.getRight();
return root;
}
if (root.getRight() == null && root.getLeft() != null){// 如果删除结点只有左子树
root = root.getLeft();
return root;
}
if (root.getLeft() != null && root.getRight() != null){// 如果删除结点为父结点
int val = findMaxInLeftTree(root.getLeft());// 让左子树中最大或者右子树中最小的结点替换当前节点,同时将置换结点置空
root.setData(val);
root.setLeft(delete(root.getLeft(),val));
return root;
}
return root;
}
完整代码
public class Binarysorttree2 {
public static void main(String[] args) {
int arr[]= {3,1,8,9,6,4,7};
binarysorttree binary=new binarysorttree();
for(int i=0;i<arr.length;i++) {//创建二叉排序树
binary.add(new Node(arr[i]));
}
System.out.println("----创建二叉排序树完成----");
System.out.println("前序遍历结果为:");
binary.preorder();
System.out.println("中序排序结果为:");
binary.infixorder();
binary.deleteNode(8);
System.out.println("----删除结点后二叉排序排序树----");
System.out.println("前序遍历结果为:");
binary.preorder();
System.out.println("中序排序结果为:");
binary.infixorder();
System.out.println("----查询结点----");
binary.search(9);
}
}
class binarysorttree{
private Node root;
public void add(Node no) {//添加结点
if(root==null) {
root=no;
}else {
root.add(no);
}
}
public void deleteNode(int data) {//删除结点
if(root==null) {
System.out.println("二叉排序树为空,无法删除结点!");
}else {
root.delete(root, data);
}
}
public void search(int data) {
root.search(data);
}
//前序遍历
public void preorder() {
if(root==null) {
System.out.println("二叉排序树为空!");
}else {
root.preorder();
}
System.out.println();
}
//中序遍历
public void infixorder() {
if(root==null) {
System.out.println("二叉树为空!");
}else {
root.infixorder();
}
System.out.println();
}
}
class Node{
int data;
int flag;
Node left;
Node right;
public Node(int data) {
this.data=data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public int hashCode() {
return right.hashCode();
}
public boolean equals(Object obj) {
return right.equals(obj);
}
@Override
public String toString() {
return data + " ";
}
//前序遍历
public void preorder() {
System.out.print(this);
if(this.left!=null) {
this.left.preorder();
}
if(this.right!=null) {
this.right.preorder();
}
}
//中序遍历
public void infixorder() {
if(this.left!=null) {
this.left.infixorder();
}
System.out.print(this);
if(this.right!=null) {
this.right.infixorder();
}
}
public void add(Node no) {//添加结点
if(no==null) {
return;
}
if(no.data!=this.data) {
if(no.data<this.data) {//如果插入结点小于当前结点,则放在左子树
if(this.left==null) {
this.left=no;
}else {//递归向左子树递归
this.left.add(no);
}
}
if(no.data>this.data) {//如果插入结点大于当前结点,则放在右子树
if(this.right==null) {
this.right=no;
}else {//递归向右子树递归
this.right.add(no);
}
}
}
}
public void search(int data) {//查找结点
if(data==this.data) {
System.out.printf("查询到%d结点",data);
}else if(data<this.data) {//查找元素小于当前元素,则向左子树递归
if(this.left==null) {
System.out.println("二叉排序树中没有该结点!");
}
this.left.search(data);
}else {//查找元素大于当前结点元素,则向右子树递归
if(this.right==null) {
System.out.println("二叉排序树中没有该结点!");
}
this.right.search(data);
}
}
public Node delete(Node root, int key) {//删除结点
if (root == null)
{
return null;
}
if (key < root.getData()){// 向左子树进行删除
root.setLeft(delete(root.getLeft(), key));
return root;
}
if (key > root.getData()){// 向右子树进行删除
root.setRight(delete(root.getRight(), key));
return root;
}
if (root.getLeft() == null && root.getRight() == null){// 如果删除结点是叶子节点
root = null;
return root;
}
if (root.getLeft() == null && root.getRight() != null){// 如果删除结点只有右子树
root = root.getRight();
return root;
}
if (root.getRight() == null && root.getLeft() != null){// 如果删除结点只有左子树
root = root.getLeft();
return root;
}
if (root.getLeft() != null && root.getRight() != null){// 如果删除结点为父结点
int val = findMaxInLeftTree(root.getLeft());// 让左子树中最大或者右子树中最小的结点替换当前节点,同时将置换结点置空
root.setData(val);
root.setLeft(delete(root.getLeft(),val));
return root;
}
return root;
}
private static int findMaxInLeftTree(Node left) {// 找到左子树中最大的节点的值
if (left == null)
{
return 0;
}
if (left.getRight() == null)
{
return left.getData();
}
if (left.getRight() == null && left.getLeft() == null)
{
return left.getData();
}
return findMaxInLeftTree(left.getRight());
}
}
运行结果
----创建二叉排序树完成----
前序遍历结果为:
3 1 8 6 4 7 9
中序排序结果为:
1 3 4 6 7 8 9
----删除结点后二叉排序排序树----
前序遍历结果为:
3 1 7 6 4 9
中序排序结果为:
1 3 4 6 7 9
----查询结点----
查询到9结点