--也许有错,欢迎指点
{
public Object element;
public Node left;
public Node right;
public int height;
public Node[] path =new Node[32];
public Node(Object data,Node lt,Node rt)
{
element =data;
left=lt;
right=rt;
height=0;
}
public int CompareTo(Object obj)
{
return (((int)element.CompareTo((int)obj));
}
public int GetHeight()
{
if(this==null)
return -1;
else
return this.height;
}
public Node insert(Object item,Node n)
{
if (n==null) //若为空 直接插入
n=new Node(item,null,null);
else if (((int)item).CompareTo((int)n.element)<0) //否则就比较值 小于这个节点就与这个节点的做儿子比较
{
n.left=insert(item,n.left); //递归
if(n.left.GetHeight()-n.right.GetHeight()==2) //如果左节点比有节点高度多二 则不符合平衡状态
if (((int)item).CompareTo((int)n.left.element)<0) //如果插入的值比左节点要小 就符合了单独右旋转
n=left(n);
else n=DoubleWithLeft(n); //否则就是先子节点右旋转 然后在根节点左旋转
}
if(((int)item).CompareTo((int)n.element)>0)
{
n.right=insert(item,n.right)
if(n.right.GetHeight()-n.left.GetHeight()==2)
if(((int)item).CompareTo((int)n.right.element)>0)
n=right(n);
else n=DoubleWithRight(n);
}
n.height=Math.Max(n.left.GetHeight(),n.right.GetHeight())+1;
return n;
}
- - - - - 输入要删的值 先找到位置 然后引用RemoveNode方法
public bool find(int val, Node n)
{
while (n != null)
{
if (val.CompareTo((int)n.element) > 0)
n = n.right;
else if (val.CompareTo((int)n.element) < 0)
n = n.left;
else break;
}
if ((int)n.element == val)
{
RemoveNode(n);
return true;
}
else return false;
}
- - - - -利用Node Path【】储存删除掉的那个节点的那一条 然后看哪里的节点不符合平衡状态 在旋转
public Node RemoveNode(Node node)
{
Node j = node;
if (node.left != null)
{
node = node.left;
while (node.right != null)
{
node = node.right;
path[v] = node;
v++;
}
j.element = node.element;
node = node.left;
}
else if (node.right != null)
{
node = node.right;
while (node.left != null)
{
node = node.left;
path[v++] = node;
}
j.element = node.element;
node = node.right;
}
else node = null;
while(v!=0)
{
v -= 1;
if((path[v].left.GetHeight())-(path[v].right.GetHeight())==2)
{
if ((path[v].left.left.GetHeight()) - (path[v].left.right.GetHeight()) == 1)
WithLeft(path[v]);
else DoubleWithLeft(path[v]);
}
else if ((path[v].left.GetHeight())-(path[v].right.GetHeight())==-2)
{
if ((path[v].right.left.GetHeight()) - (path[v].right.right.GetHeight()) == -1)
WithRight(path[v]);
else DoubleWithRight(path[v]);
}
}
return j;
}
avl树的是四种旋转(图片来自百度):
单独的右旋转:
private Node right(Node n1)
{
Node n2 = n1.right; //先把子节点放在n2 上
n1.right=n2.left; //把子节点下的左儿子节点放在子节点原来的位置
n2.left=n1; //把子节点的父亲放在N2的左儿子节点上
n1.height=Math.Max(n1.left.GetHeight(),n1.right.GetHeight())+1;
n2.height=Math.Max(n2.left.GetHeight(),n1.height)+1; //记录高度
return n2;
}
单独的左旋转:
private Node left(Node n2)
{
Node n1=n2.left;
n2.left=n1.right;
n1.right=n2;
n2.height=Math.Max(n2.left.GetHeight(),n2.right.GetHeight())+1;
n1.height=Math.Max(n1.left.GetHeight(),n2.height)+1;
return n1;}
先对子节点的右旋转在对跟节点左旋转:
private Node DoubleWithLeft(Node n3)
{
n3.left=right(n3.left);
return left(n3);
}
先对子节点的左旋转在对根节点的右旋转:
private Node DoubleWithRight(Noed n4)
{
n4.right=left(n4.right);
return right(n4);
}