搜索二叉树,平衡二叉树,B树,B+树
一.搜索二叉树
//插入某个元素
private boolean insertItem(TreeNode<E> root,E element)//E表示一个类型
{
TreeNode<E>node=new TreeNode<>();
node.setElement(element);
if(root==NULL)
{
this.root=node;return true;
}
while(root!=NULL)
{
int compare_root=element.compareTo(root.element);
if(compare_root<0)
{
if(root.left==NULL)
{
root.left=node;return true;
}
else
root=root.left;
}
else if(compare_root>0)
{
if(root.right==NULL)
{
root.right=node;return true;
}
else
root=root.right;
}
}
return false;
}
//查找某个节点的元素值
private TreeNode<E> searchItem(TreeNode<E> root,E contactKey)
{
while(root!=NULL){
if(contactKey.compareTo(root.element)>0)
root=root.right;
else if(contactKey.compareTo(root.element)<0)
root=root.left;
else if(contactKey.compareTo(root.element)==0)
return root;
}
return NULL;
}
//删除某个结点
private boolean removeElement(TreeNode<E> root, E removeElement)//removeElement是要删除的结点
{
if(root!=NULL){
TreeNode<E> search_node=searchItem(root,removeElement);
if(search_node==NULL)return false;
else
{
if(search_node.left==NULL&&search_node.right==NULL)
{
search_node=NULL;return true;
}
else if(search_node.left==NULL&&search_node.right!=NULL)
{
TreeNode<E> temp=search_node.right;
if(temp.left!=NULL)
search_node.left=temp.left;
if(temp.right!=NULL)
search_node.right=temp.right;
search_node=temp;//或者只做值替换,即只把temp的element赋值给search_node
return true;
}
else if(search_node.left!=NULL&&search_node.right==NULL)
{
TreeNode<E> Node=search_node.left;
if(temp.left!=NULL)
search_node.left=temp.left;
if(temp.right!=NULL)
search_node.right=temp.right;
search_node=temp;
return true;
}
else if(search_node.left!=NULL&&search_node.right!=NULL)
//当删除的结点既有左子树又有右子树时,用左子树的最大结点或者右子树的最小结点来代替要删除的结点,这样依然满足搜索二叉树的性质
{
//1.找到继承者父结点
TreeNode<E> successorParent =findsuccessorParent(search_node.right)//要从其右子树开始找起
//2.替换
search_node.element=successorParent.left.element;
//3.删除继承者的结点
if(successorParent .left.right!=NULL)//如果继承者不是叶子
{
successorParent.left=successorParent.left.right;
}
else //继承者是叶子
{
successorParent.left=NULL;
}
return true;
}
}
}
return false;
}
private TreeNode<E> findSuccessorParent(TreeNode<E> currentNode)//类方法,找到继承者的父结点(私有)
{
TreeNode<E> temp=currentNode;
TreeNode<E> parent;
Stack<TreeNode<E>>stack=new Stack<>();
while(temp!=NULL||!stack.IsEmpty)
{
while(temp!=NULL)
{
stack.push(temp);
temp=temp.left;
}
if(!stack.IsEmpty)
{
stack.pop();
return stack.pop();//相当于连弹两次,弹出的来是继承者的父结点
}
}
return NULL;//没有找到
}
二.平衡二叉树(AVL)
需要满足两个条件:
1.任意子树都是二叉排序树
2.任意结点的子树都是平衡二叉树(左右结点的高度差不超过1)
public class ALVNode
{
public int data;
public int height;
public ALVNode left;
public ALVNode right;
public ALVNode parent;
public ALVNode(int data)
{
this.data=data;
this.height=1;
}
}
//计算高度
public int GetDepth(ALVNode tree)
{
if(tree==NULL)return 0;
int leftdepth=GetDepth(tree.left);
int rightdepth=GetDepth(tree.right);
return leftdepth>rightdepth?leftdepth+1:rightdepth+1;
}//递归法求高度
//第二种方法
public int GetDepth(ALVNode root)
{
if(root.left==NULL&&root.right==NULL)return 1;
else if(root.left==NULL&&root.right!=NULL)return root.right.height+1;
else if(root.right==NULL&&root.left!=-NULL)return root.left.height+1;
else
{
return root.left.height>root.right.height?root.left.height+1:root.right.height+1;
}
}
//计算平衡因子
public int cacBF(ALVNode root)
{
if(root.right==NULL&&root.left==NULL)return 0;
else if(root.left==NULL)return 0-root.right.height;
else if(root.right==NULL)return root.left.height;
else return root.left.height-root.right.height;
}
//左旋
public ALVNode left_revolve(ALVNode root)
{
ALVNode oldNode=root;
ALVNode newNode=root.right;
ALVNode parent=root.parent;
if(parent!=NULL)//判断新子树接到根节点父结点的左边还是右边
{
if(parent.data>oldNoot.data)//接左边
{
parent.left=newNode;
}
else
parent.right=newNode;
}
newNode.parent=parent;
//然后把新结点的左结点赋给老结点的右结点
oldNode.right=newNode.left;
if(newNode.left!=NULL)
{
newNode.left.parent=oldNode;
}
//然后把newNode.left更新一下
newNode.left=oldNode;
oldNode.parent=newNode;
//最后更新一下新旧结点的高度
oldNode.height=GetDepth(oldNode);
newNode.height=GetDepth(newNode);
return newNode;
}
//右旋
public ALVNode right_revolve(ALVNode root)
{
ALVNode oldNode=root;
ALVNode newNode=root.right;
ALVNode parent=root.parent;
if(parent!=NULL)//判断新子树接到根节点父结点的左边还是右边
{
if(parent.data>oldNoot.data)//接左边
{
parent.left=newNode;
}
else
parent.right=newNode;
}
newNode.parent=parent;
//然后把新结点的左结点赋给老结点的右结点
oldNode.left=newNode.right;
if(newNode.right!=NULL)
{
newNode.right.parent=oldNode;
}
//然后把newNode.right更新一下
newNode.right=oldNode;
oldNode.parent=newNode;
//最后更新一下新旧结点的高度
oldNode.height=GetDepth(oldNode);
newNode.height=GetDepth(newNode);
return newNode;
}
public ALVNode Insert(ALVNode root,int data)
{
if(root.data>data)
{
ALVNode newNode=new ALVNode(data);
if(root.left==NULL)
{
root.left=newNode;
newNode.parent=root;
}
else
Insert(root.left,data);
}
else if(root.data<data)
{
ALVNode newNode=new ALVNode(data);
if(root.right==NULL)
{
root.right=newNode;
newNode.parent=root;
}
else
Insert(root.right,data);
}
GetDepth(root);
//更新一下root的高度
if(cacBF(root)==2)LL型
{
if(cacBF(root.left)==-1)//LR型
root.left=left_rovolve(root.left);
root=right_revolve(root);
}
else if(cacBF(root)==-2)RR型
{
if(cacBF(root.left)==1)RL型
right.left= right_revolve(root.left);
root=left_revolve(root);
}
return root;
}
三.B树
B树和AVL树(平衡二叉树) 的差别就是 B树 属于多叉树,又名平衡多路查找树,即一个结点的查找路径不止左、右两个,而是有多个。数据库索引技术里大量使用者B树和B+树的数据结构。一个结点存储多个值(索引)。