彻底理清二叉排序树的插入、查找、删除
二叉排序树的概述
二叉排序树也被成为二叉查找树或者二叉搜索树。它或者是一棵空的二叉树。它具备以下性质。
若它的左子树不空,则左子树上所有结点的值均小于根结点的值。
若它的右子树不空,则右子树上所有结点的值均大于根结点的值。
它的左右子树也都是二叉排序树。
简述二叉排序树原理与实现
二叉排序树的建立根基是二叉链表。
//二叉树节点
public class BinaryTreeNode {
public int data;
public BinaryTreeNode left;
public BinaryTreeNode right;
}
假设有这样一组数据{11,2,5,7,3,9,4,66,55},那么它将构造这样一棵树结构。

如何对搜索二叉树插入节点,从而构建一颗二叉树?
根据二叉树的定义,向二叉排序树中插入节点s的过程,用伪代码描述:
若root是空树,则将节点s作为根结点输入;
否则,若s.data<root.data,则把节点s插入在root的左子树中;
否则把结点s插入到root的右子树中;
//构建搜索二叉树
public BinaryTreeNode build(int [] array){
BinaryTreeNode root =new BinaryTreeNode(array[0]);
for( int i = 1 ; i < array.length ; i ++){
insertBST(root, array[i]);
}
return root;
}
public BinaryTreeNode insertBST(BinaryTreeNode node,int data){
if(node == null){
node = new BinaryTreeNode(data);
return node;
}else{
if(data <= node.data)
node.left = insertBST(node.left, data);
else
node.right = insertBST(node.right,data);
return node;
}
}
查找二叉树的指定值。
若root是空树,则查找失败。
若k=root.data,则查找成功。
若k<root.data,则查找二叉树的左子树。
若k>root.data,则查找二叉树的右子树。
//查找元素
public BinaryTreeNode serachBST(BinaryTreeNode root,int target){
if(null==root)
return null;
else if(root.getData()==target)
return root;
else if(root.getData()>target)
return serachBST(root.getLeft(), target);
else
return serachBST(root.getRight(), target);
}
删除二叉树的指定值。删除元素其实并不难,重点是删除要元素以后依然要保持二叉搜索树,不能让它头脚分离变成森林。
假设要删除结点为p(2),节点分为三种类型,p是叶子节点,p只有一个孩子,p有两个孩子。
情况一:假设p是叶子节点,只需要把p设为null即可。
情况二:假设p有一个孩子。假设它有左孩子,那么把p节点等于左孩子;假设它有右孩子,那么把p节点等于右孩子。
情况三:假设p有两个孩子。
查找p节点右子树的最左子树节点,也就是p节点的右子树的最小结点s,以及s的双亲节点par;
将s的数据域替换被删除结点p的数据域;
若节点p的右孩子无子树,则将s的右子树接到par的右子树上;否则,将s的右子树接到par的左字数上;
图例原始图

图例情况一:假设删除结点p为9,无孩子节点。

图例情况二:假设删除节点p为3,有右孩子节点。

图例情况三:假设删除节点p为5,有左右孩子。

public BinaryTreeNode deleteBST(BinaryTreeNode root,int key){
if(root==null){
return null;
}
if(root.data==key){
return deleteNode(root);
}else if(root.data<key){
root.right=deleteBST(root.right, key);
}else{
root.left=deleteBST(root.left, key);
}
return root;
}
//删除元素
public BinaryTreeNode deleteNode(BinaryTreeNode p){
if(nullp.left&&nullp.right){
p=null;//无孩子节点
}else if(p.leftnull){
p=p.right;//只有右孩子
}else if(p.rightnull){
p=p.left;//只有左孩子
}else{
BinaryTreeNode par=p;
BinaryTreeNode s=p.right;
while(s.left!=null){
par=s;
s=s.left;
}
p.data=s.data;
if(par==p){
par.right=s.right;//处理特殊情况,par节点没有左孩子
}else{
par.left=s.right;//处理一般情况,p节点替换成par的最左节点。
}
}
return p;
}
发散思考-更进一步
假设一颗二叉树为是一颗右斜树,二叉搜索树的优势也将荡然无存。那问题出在哪?就是构造二叉树的时候,就是我们改善的着手点。
那么就引出了平衡二叉树的概念,那什么是平衡二叉树呢?
平衡二叉树或者是一棵空的二叉树,或者是具有以下性质的二叉树。
根结点的左子树和右子树的深度最多相差1。
根结点的左子树和右子树也都是平衡二叉树。
那如何构建一颗平衡二叉树呢?先对数组进行排序,然后像折半查找一样,向两侧平均构造二叉树。当排序的数值多的时候,它将提高查找效率。

//构建平衡搜索二叉树
public BinaryTreeNode buildBlanceTree(int [] array,int start,int end){
if(start>end)
return null;
int mid=(start+end)/2;
BinaryTreeNode node=new BinaryTreeNode(array[mid]);
if(start==end){
return node;
}
node.left=buildBlanceTree(array, start,mid-1);
node.right=buildBlanceTree(array, mid+1,end);
return node;
}
善于思考的大佬们又脑洞大开了,直接删除节点、插入节点的时候,若产生不平衡,重构平衡二叉树岂不是难上加难?具体代码又读者自行思考完成。
平衡二叉树分为四种类型:LL型、RR型、LR型、RL型。

LR型:不平衡点的左子树左转,以不平衡点为基点向右转。RL型:不平衡点的右子树右转,以补平衡点为基点向左转。

public class BinaryTreeNode {
public int data;
public BinaryTreeNode left;
public BinaryTreeNode right;
public BinaryTreeNode() {}
public BinaryTreeNode(int data, BinaryTreeNode left, BinaryTreeNode right) {
super();
this.data = data;
this.left = left;
this.right = right;
}
public BinaryTreeNode(int data) {
this(data,null,null);
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public BinaryTreeNode getLeft() {
return left;
}
public void setLeft(BinaryTreeNode left) {
this.left = left;
}
public BinaryTreeNode getRight() {
return right;
}
public void setRight(BinaryTreeNode right) {
this.right = right;
}
}
public class BinarySortTree {
public BinarySortTree(){}
//构建搜索二叉树
public BinaryTreeNode build(int [] array){
BinaryTreeNode root =new BinaryTreeNode(array[0]);
for( int i = 1 ; i < array.length ; i ++){
insertBST(root, array[i]);
}
return root;
}
//构建平衡搜索二叉树
public BinaryTreeNode buildBlanceTree(int [] array,int start,int end){
if(start>end)
return null;
int mid=(start+end)/2;
BinaryTreeNode node=new BinaryTreeNode(array[mid]);
if(start==end){
return node;
}
node.left=buildBlanceTree(array, start,mid-1);
node.right=buildBlanceTree(array, mid+1,end);
return node;
}
public BinaryTreeNode insertBST(BinaryTreeNode node,int data){
if(node == null){
node = new BinaryTreeNode(data);
return node;
}else{
if(data <= node.data)
node.left = insertBST(node.left, data);
else
node.right = insertBST(node.right,data);
return node;
}
}
//层序遍历
public void levelOrder(BinaryTreeNode root){
BinaryTreeNode temp;
Queue<BinaryTreeNode> queue=new LinkedList<BinaryTreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
temp=queue.poll();
System.out.print(temp.getData()+"\t");
if(null!=temp.getLeft())
queue.offer(temp.getLeft());
if(null!=temp.getRight()){
queue.offer(temp.getRight());
}
}
}
public BinaryTreeNode deleteBST(BinaryTreeNode root,int key){
if(rootnull){
return null;
}
if(root.datakey){
return deleteNode(root);
}else if(root.data<key){
root.right=deleteBST(root.right, key);
}else{
root.left=deleteBST(root.left, key);
}
return root;
}
//删除元素
public BinaryTreeNode deleteNode(BinaryTreeNode p){
if(nullp.left&&nullp.right){
p=null;//无孩子节点
}else if(p.leftnull){
p=p.right;//只有右孩子
}else if(p.rightnull){
p=p.left;//只有左孩子
}else{
BinaryTreeNode par=p;
BinaryTreeNode s=p.right;
while(s.left!=null){
par=s;
s=s.left;
}
p.data=s.data;
if(par==p){
par.right=s.right;//处理特殊情况,par节点没有左孩子
}else{
par.left=s.right;//处理一般情况,p节点替换成par的最左节点。
}
}
return p;
}
//查找元素
public BinaryTreeNode serachBST(BinaryTreeNode root,int target){
if(nullroot)
return null;
else if(root.getData()target)
return root;
else if(root.getData()>target)
return serachBST(root.getLeft(), target);
else
return serachBST(root.getRight(), target);
}
public static void main(String[] args) {
int [] array=new int[]{11,2,5,7,3,9,4,66,55};
BinarySortTree bst=new BinarySortTree();
//构建一颗搜索二叉树
BinaryTreeNode root=bst.build(array);
System.out.println(bst.serachBST(root, 9).getData());
bst.levelOrder(root);
System.out.println();
//构建一颗平衡搜索二叉树
Arrays.sort(array);
BinaryTreeNode node=bst.buildBlanceTree(array, 0,array.length-1);
System.out.println(bst.serachBST(root, 11).getData());
bst.levelOrder(node);
System.out.println();
BinaryTreeNode n=bst.deleteBST(root,2);
bst.levelOrder(n);
System.out.println();
}
}


浙公网安备 33010602011771号