二叉排序树的概述
二叉排序树也被成为二叉查找树或者二叉搜索树。它或者是一棵空的二叉树。它具备以下性质。
若它的左子树不空,则左子树上所有结点的值均小于根结点的值。
若它的右子树不空,则右子树上所有结点的值均大于根结点的值。
它的左右子树也都是二叉排序树。
简述二叉排序树原理与实现
二叉排序树的建立根基是二叉链表。
//二叉树节点
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;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">删除元素</span>
<span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode deleteNode(BinaryTreeNode p){
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==p.left&&<span style="color: #0000ff;">null</span>==<span style="color: #000000;">p.right){
p</span>=<span style="color: #0000ff;">null</span>;<span style="color: #008000;">//</span><span style="color: #008000;">无孩子节点</span>
}<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.left==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
p</span>=p.right;<span style="color: #008000;">//</span><span style="color: #008000;">只有右孩子</span>
}<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.right==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
p</span>=p.left;<span style="color: #008000;">//</span><span style="color: #008000;">只有左孩子</span>
}<span style="color: #0000ff;">else</span><span style="color: #000000;">{
BinaryTreeNode par</span>=<span style="color: #000000;">p;
BinaryTreeNode s</span>=<span style="color: #000000;">p.right;
</span><span style="color: #0000ff;">while</span>(s.left!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
par</span>=<span style="color: #000000;">s;
s</span>=<span style="color: #000000;">s.left;
}
p.data</span>=<span style="color: #000000;">s.data;
</span><span style="color: #0000ff;">if</span>(par==<span style="color: #000000;">p){
par.right</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理特殊情况,par节点没有左孩子</span>
}<span style="color: #0000ff;">else</span><span style="color: #000000;">{
par.left</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理一般情况,p节点替换成par的最左节点。</span>
}
}
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型:不平衡点的右子树右转,以补平衡点为基点向左转。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class BinaryTreeNode {
public int data;
public BinaryTreeNode left;
public BinaryTreeNode right;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode() {}
</span><span style="color: #0000ff;">public</span> BinaryTreeNode(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data, BinaryTreeNode left, BinaryTreeNode right) {
</span><span style="color: #0000ff;">super</span><span style="color: #000000;">();
</span><span style="color: #0000ff;">this</span>.data =<span style="color: #000000;"> data;
</span><span style="color: #0000ff;">this</span>.left =<span style="color: #000000;"> left;
</span><span style="color: #0000ff;">this</span>.right =<span style="color: #000000;"> right;
}
</span><span style="color: #0000ff;">public</span> BinaryTreeNode(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data) {
</span><span style="color: #0000ff;">this</span>(data,<span style="color: #0000ff;">null</span>,<span style="color: #0000ff;">null</span><span style="color: #000000;">);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getData() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> data;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setData(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data) {
</span><span style="color: #0000ff;">this</span>.data =<span style="color: #000000;"> data;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode getLeft() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> left;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setLeft(BinaryTreeNode left) {
</span><span style="color: #0000ff;">this</span>.left =<span style="color: #000000;"> left;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode getRight() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> right;
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setRight(BinaryTreeNode right) {
</span><span style="color: #0000ff;">this</span>.right =<span style="color: #000000;"> right;
}
}
public class BinarySortTree {
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinarySortTree(){}
</span><span style="color: #008000;">//</span><span style="color: #008000;">构建搜索二叉树</span>
<span style="color: #0000ff;">public</span> BinaryTreeNode build(<span style="color: #0000ff;">int</span><span style="color: #000000;"> [] array){
BinaryTreeNode root </span>=<span style="color: #0000ff;">new</span> BinaryTreeNode(array[0<span style="color: #000000;">]);
</span><span style="color: #0000ff;">for</span>( <span style="color: #0000ff;">int</span> i = 1 ; i < array.length ; i ++<span style="color: #000000;">){
insertBST(root, array[i]);
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">构建平衡搜索二叉树</span>
<span style="color: #0000ff;">public</span> BinaryTreeNode buildBlanceTree(<span style="color: #0000ff;">int</span> [] array,<span style="color: #0000ff;">int</span> start,<span style="color: #0000ff;">int</span><span style="color: #000000;"> end){
</span><span style="color: #0000ff;">if</span>(start><span style="color: #000000;">end)
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">int</span> mid=(start+end)/2<span style="color: #000000;">;
BinaryTreeNode node</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> BinaryTreeNode(array[mid]);
</span><span style="color: #0000ff;">if</span>(start==<span style="color: #000000;">end){
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
}
node.left</span>=buildBlanceTree(array, start,mid-1<span style="color: #000000;">);
node.right</span>=buildBlanceTree(array, mid+1<span style="color: #000000;">,end);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
}
</span><span style="color: #0000ff;">public</span> BinaryTreeNode insertBST(BinaryTreeNode node,<span style="color: #0000ff;">int</span><span style="color: #000000;"> data){
</span><span style="color: #0000ff;">if</span>(node == <span style="color: #0000ff;">null</span><span style="color: #000000;">){
node </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> BinaryTreeNode(data);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
</span><span style="color: #0000ff;">if</span>(data <=<span style="color: #000000;"> node.data)
node.left </span>=<span style="color: #000000;"> insertBST(node.left, data);
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">
node.right </span>=<span style="color: #000000;"> insertBST(node.right,data);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
}
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">层序遍历</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> levelOrder(BinaryTreeNode root){
BinaryTreeNode temp;
Queue</span><BinaryTreeNode> queue=<span style="color: #0000ff;">new</span> LinkedList<BinaryTreeNode><span style="color: #000000;">();
queue.offer(root);
</span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
temp</span>=<span style="color: #000000;">queue.poll();
System.out.print(temp.getData()</span>+" "<span style="color: #000000;">);
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>!=<span style="color: #000000;">temp.getLeft())
queue.offer(temp.getLeft());
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>!=<span style="color: #000000;">temp.getRight()){
queue.offer(temp.getRight());
}
}
}
</span><span style="color: #0000ff;">public</span> BinaryTreeNode deleteBST(BinaryTreeNode root,<span style="color: #0000ff;">int</span><span style="color: #000000;"> key){
</span><span style="color: #0000ff;">if</span>(root==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">if</span>(root.data==<span style="color: #000000;">key){
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> deleteNode(root);
}</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.data<<span style="color: #000000;">key){
root.right</span>=<span style="color: #000000;">deleteBST(root.right, key);
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
root.left</span>=<span style="color: #000000;">deleteBST(root.left, key);
}
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">删除元素</span>
<span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode deleteNode(BinaryTreeNode p){
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==p.left&&<span style="color: #0000ff;">null</span>==<span style="color: #000000;">p.right){
p</span>=<span style="color: #0000ff;">null</span>;<span style="color: #008000;">//</span><span style="color: #008000;">无孩子节点</span>
}<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.left==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
p</span>=p.right;<span style="color: #008000;">//</span><span style="color: #008000;">只有右孩子</span>
}<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.right==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
p</span>=p.left;<span style="color: #008000;">//</span><span style="color: #008000;">只有左孩子</span>
}<span style="color: #0000ff;">else</span><span style="color: #000000;">{
BinaryTreeNode par</span>=<span style="color: #000000;">p;
BinaryTreeNode s</span>=<span style="color: #000000;">p.right;
</span><span style="color: #0000ff;">while</span>(s.left!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
par</span>=<span style="color: #000000;">s;
s</span>=<span style="color: #000000;">s.left;
}
p.data</span>=<span style="color: #000000;">s.data;
</span><span style="color: #0000ff;">if</span>(par==<span style="color: #000000;">p){
par.right</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理特殊情况,par节点没有左孩子</span>
}<span style="color: #0000ff;">else</span><span style="color: #000000;">{
par.left</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理一般情况,p节点替换成par的最左节点。</span>
}
}
return p;
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">查找元素</span>
<span style="color: #0000ff;">public</span> BinaryTreeNode serachBST(BinaryTreeNode root,<span style="color: #0000ff;">int</span><span style="color: #000000;"> target){
</span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==<span style="color: #000000;">root)
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.getData()==<span style="color: #000000;">target)
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.getData()><span style="color: #000000;">target)
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> serachBST(root.getLeft(), target);
</span><span style="color: #0000ff;">else</span>
<span style="color: #0000ff;">return</span><span style="color: #000000;"> serachBST(root.getRight(), target);
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
</span><span style="color: #0000ff;">int</span> [] array=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">int</span>[]{11,2,5,7,3,9,4,66,55<span style="color: #000000;">};
BinarySortTree bst</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> BinarySortTree();
</span><span style="color: #008000;">//</span><span style="color: #008000;">构建一颗搜索二叉树</span>
BinaryTreeNode root=<span style="color: #000000;">bst.build(array);
System.out.println(bst.serachBST(root, </span>9<span style="color: #000000;">).getData());
bst.levelOrder(root);
System.out.println();
</span><span style="color: #008000;">//</span><span style="color: #008000;">构建一颗平衡搜索二叉树</span>
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</span>=bst.deleteBST(root,2<span style="color: #000000;">);
bst.levelOrder(n);
System.out.println();
}
}