二叉排序树的建立,删除,遍历,查找,最大值,最小值--java实现

目录

 

二叉排序树(Binary Sort Tree)

定义

二叉排序树的建立

二叉排序树的遍历

二叉排序树的查找

二叉树的最小值,最大值

二叉树的删除

总结:


二叉排序树(Binary Sort Tree)

又称二叉查找数(Binary Search Tree),亦称二叉搜索树。

定义

 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

  • 若左子树不空,则左子树上所有结点的值均小于它的根节点的值;

  • 若右子树不空,则右子树上所有结点的值均大于它的根节点的值;

  • 左、右子树也分别为二叉排序树;

  • 没有键值相等的节点。

二叉排序树的建立

先建立一个节点类

public class Node {
	public int data;
	public Node left;
	public Node right;

	public Node(int data) {
		this.data = data;
	}

	public Node() {
	}

	@Override
	public String toString() {
		return "Node [data=" + data + "]";
	}

}

思路:按照二叉排序树的性质,左子树的节点都小于它父节点的值,右子树的节点都大于它父节点的值。当需要插入一个节点时,假设树为空,则新建一颗树,假设树不为空,则按照二叉排序树的性质,找到当前值应该在这树那个位置。以下图二叉排序树为例,插入一个40的值,40小于根节点的50,走左孩子到20,40大于20,则去20的右孩子30,30小于40,则走30的右孩子,但右孩子为null,为30的右孩子为40。

            

public class BinarySearchTree {

    private Node root;

    public void add(int val) {
		if (root == null) {
			//当树为空时,新建一个根节点
			root = new Node(val);
		} else {
			//当树不为空时
			Node next = root;
			//进行遍历二叉树,搜索当前值放那个位置
			while (next != null) {
				if (val > next.data) {
					//如果next的右孩子节点为空,那么新增一个节点作为next的右孩子节点
					//不为空则继续遍历
					if (next.right == null) {
						next.right = new Node(val);
						break;
					} else {
						next = next.right;
					}
				} else {
					if (next.left == null) {
						next.left = new Node(val);
						break;
					} else {
						next = next.left;
					}
				}

			}
		}
	}

}

二叉排序树的遍历

根据二叉排序树的性质,按照树的中序遍历即可遍历出二叉排序树从小到大排序的结果。

    public void show() {
		show(root);
	}

	private void show(Node next) {
		if (next.left != null) {
			show(next.left);
		}
		System.out.print(next.data + " ");
		if (next.right != null) {
			show(next.right);
		}
	}

二叉排序树的查找

二叉排序树查找依靠它本身的性质,与二分查找类似,假设二叉树的节点数为n,树的高度为log2n + 1,则查找的效率为O(log2n),近似于二分查找,但最坏的情况为O(n)。

public boolean index(int val) {
		if (root == null) {
			return false;
		} else {
			Node next = root;
			while (next != null) {
				if (next.data == val) {
					return true;
				} else if (next.data > val) {
					if (next.right == null) {
						return false;
					}
					next = next.right;
				} else {
					if (next.left == null) {
						return false;
					}
					next = next.left;
				}
			}
			return false;
		}
	}

二叉树的最小值,最大值

二叉树的最小值为最左边的节点的值。二叉树的最小值为最右边的节点的值。

   public Integer min() {
		if (root == null) {
			return null;
		} else {
			Node next = root;
			while (next.left != null) {
				next = next.left;
			}
			return next.data;
		}
	}
    public Integer max() {
		if (root == null) {
			return null;
		} else {
			Node next = root;
			while (next.right != null) {
				next = next.right;
			}
			return next.data;
		}
	}

二叉树的删除

1.若删除的节点为叶子节点,直接删除,比如下图删除55这个值。

2.若删除的节点有一个孩子节点,则孩子节点替换被删除的节点,下图中,二叉排序树删除60这个值。

 

3.若删除的节点有2个孩子节点,则找右子树最小的节点替代被删除的节点,若删除50这个值,则找到他右孩子中最小的值55,替代该节点。

public Integer delete(int val) {
		if (root == null) {
			return -1;
		} else {
			Node next = root;
			Node parent = null;
			while (next != null) {
				if (next.data > val) {
					if (next.left != null) {
						parent = next;
						next = next.left;
					} else {
						//没找到该删除的值
						return -1;
					}
				} else if (next.data == val) {
					//没有孩子节点,被删除的节点的父节点直接删除该节点
					if (next.left == null && next.right == null) {
						if (next.data > parent.data) {
							parent.right = null;
						} else {
							parent.left = null;
						}
					}
					//有一个节点,则替换
					else if (next.left == null && next.right != null) {
						if (next.data > parent.data) {
							parent.right = next.right;
						} else {
							parent.left = next.right;
						}
					} else if (next.left != null && next.right == null) {
						if (next.data > parent.data) {
							parent.right = next.left;
						} else {
							parent.left = next.left;
						}
					} else {
						//找到右子树中最小的节点
						Node temp = next.right;
						Node tparent = next;
						if (temp.left != null) {
							while (temp.left != null) {
								tparent = temp;
								temp = temp.left;
							}
							tparent.left = null;
						}
						//该节点保留右子树最小的节点的右孩子
						Node houxu = null;
						if (temp.right != null) {
							houxu = temp.right;
							temp.right = null;
						}
						//被删除节点的左孩子
						Node nextleft = null;
						if (next.left != null) {
							nextleft = next.left;
						}
						//被删除节点的右孩子
						Node nextright = null;
						if (next.right != null) {
							nextright = next.right;
						}
						//被删除节点的父节点,替换被删除的节点
						if (parent != null) {
							if (next.data > parent.data) {
								parent.right = temp;
							} else {
								parent.left = temp;
							}
						} else {
							root = temp;
						}
						//右子树最小的节点的右孩子,作为右子树最小的节点的的父亲节点的左孩子
						if (houxu != null) {
							tparent.left = houxu;
						}
						//判断是不是右子树的最小值为 被删除节点的右孩子,是则不将被删除节点的右孩子作为替代节点的右孩子,不然形成了闭环
						if (nextright != null && next.right.data != temp.data) {
							temp.right = nextright;
						} else {
							temp.right = houxu;
						}
						//被删除节点的左孩子作为替代节点的左孩子
						if (nextleft != null) {
							temp.left = nextleft;
						}

					}
					return val;
				} else {
					if (next.right != null) {
						parent = next;
						next = next.right;
					} else {
						return -1;
					}
				}

			}
		}
		return -1;
	}

总结:

二叉查找树类似二分查找,查找速度快,但避免出现树不平衡的情况,树完全不平衡的情况下,查找效率变成线性查找,效率较低。优化考虑,避免二叉排序树出现不平衡的状态,所以考虑红黑树,以及平衡树。

猜你喜欢

转载自blog.csdn.net/qq_39290830/article/details/85063191