Java AVL树给我O(c^n)而不是O(logn)

Java AVL树给我O(c^n)而不是O(logn),java,algorithm,binary-tree,big-o,avl-tree,Java,Algorithm,Binary Tree,Big O,Avl Tree,我已经用java创建了一个AVLTree,add方法应该是O(logn)。。。然而,我的add方法似乎给了我一个O(c^n)图或指数图,而不是对数图。以下是运行时间与输入大小的关系图: 有人能帮忙弄清楚为什么会发生这种情况吗 以下是我的AVLTree的代码: import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import cw1.rs10.lib.IAVLTree; publ

我已经用java创建了一个AVLTree,add方法应该是O(logn)。。。然而,我的add方法似乎给了我一个O(c^n)图或指数图,而不是对数图。以下是运行时间与输入大小的关系图:

有人能帮忙弄清楚为什么会发生这种情况吗

以下是我的AVLTree的代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import cw1.rs10.lib.IAVLTree;

public class AVLTree<K, V> implements IAVLTree<K, V>
{
    public class Node {
        private K key;
        private ArrayList<V> values;
        private Node left, right;
        private int height;

        public Node(K key, V value) {
            this.key = key;
            this.values = new ArrayList<V>();
            this.left = null;
            this.right = null;
            this.height = 0;

            values.add(value);
        }

        public K getKey() {
            return key;
        }
        public void setKey(K key) {
            this.key = key;
        }

        public ArrayList<V> getValues() {
            return values;
        }
        public void addValue(V value) {
            values.add(value);
        }

        public Node getLeft() {
            return left;
        }
        public Node getRight() {
            return right;
        }

        public void setLeft(Node left) {
            this.left = left;
        }
        public void setRight(Node right) {
            this.right = right;
        }

        public int getHeight() {
            return height;
        }
        public void setHeight(int height) {
            this.height = height;
        }
    }

    private Node rootNode;
    private Comparator<K> comparator;

    //Unused
    public AVLTree() {
    }

    public AVLTree(Comparator<K> comparator) {
        this.rootNode = null;
        this.comparator = comparator;
    }

    @Override
    public V add(K k, V v) {
        Node n = rootNode = add(k, v, rootNode);
        if(n != null)
            return v;
        else
            return null;
    }
    private Node add(K key, V value, Node node) {
        if(node == null)
            return new Node(key, value);

        if(comparator.compare(key, node.getKey()) < 0) {
            node.setLeft(add(key, value, node.getLeft()));

            if(height(node.getLeft()) - height(node.getRight()) == 2) {
                if(comparator.compare(key, node.getLeft().getKey()) < 0)
                    node = rotateLeft(node);
                else
                    node = doubleRotateLeft(node);
            }
        } else if(comparator.compare(key, node.getKey()) > 0) {
            node.setRight(add(key, value, node.getRight()));

            if(height(node.getRight()) - height(node.getLeft()) == 2) {
                if(comparator.compare(key, node.getRight().getKey()) > 0)
                    node = rotateRight(node);
                else
                    node = doubleRotateRight(node);
            }
        } else {
            //Handle duplicate
            node.getValues().add(value);
        }

        node.setHeight( Math.max(height(node.getLeft()), height(node.getRight())) + 1 );

        return node;
    }

    @Override
    public V remove(K key, V value) throws Exception {
        Node node = rootNode = remove(key, value, rootNode);
        if(node != null)
            return value;
        else
            return null;
    }
    private Node remove(K key, V value, Node node) {
        //If node with key contains one or less values, remove the whole key
        //Else remove value from node with key
        if(node == null) return null;
        else if(comparator.compare(key, node.getKey()) < 0) {
            node.setLeft(remove(key, value, node.getLeft()));

            if(height(node.getLeft()) - height(node.getRight()) == 2) {
                if(comparator.compare(key, node.getLeft().key) < 0)
                    node = rotateLeft(node);
                else
                    node = doubleRotateLeft(node);
            }
        } else if(comparator.compare(key, node.getKey()) > 0) {
            node.setRight(remove(key, value, node.getRight()));

            if(height(node.getRight()) - height(node.getLeft()) == 2) {
                if(comparator.compare(key, node.getRight().key) < 0)
                    node = rotateRight(node);
                else
                    node = doubleRotateRight(node);
            }
        } else {
            if(node.getValues().size() > 1) {
                node.getValues().remove(value);
                return node;
            } else {
                if(node.getLeft() == null && node.getRight() == null)
                    return null;
                if(node.getLeft() == null) return node.getRight();
                if(node.getRight() == null) return node.getLeft();

                Node smallestNode = smallestNode(node.getRight());
                node = smallestNode;
                node.setRight(remove(key, value, node.getRight()));

                return node;
            }
        }
        return node;
    }

    @Override
    public Iterator<V> find(K key) {
        Node n = search(key, rootNode);
        if(n != null) {
            ArrayList<V> values = n.getValues();
            return values.iterator();
        } else {
            return new ArrayList<V>().iterator();
        }
    }
    private Node search(K key, Node node) {
        while(node != null) {
            if(comparator.compare(key, node.getKey()) < 0)
                node = node.getLeft();
            else if(comparator.compare(key, node.getKey()) > 0)
                node = node.getRight();
            else
                return node;
        }
        return null;
    }

    @Override
    public Iterator<V> removeAll(K key) {
        Node n = search(key, rootNode);
        ArrayList<V> values = n.getValues();

        try {
            remove(n.getKey(), null);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return values.iterator();
    }

    @Override
    public Iterator<V> listAll() {
        ArrayList<V> entries = new ArrayList<V>();
        listAll(rootNode, entries);
        return entries.iterator();
    }
    private void listAll(Node n, ArrayList<V> entries) {
        if(n != null) {
            listAll(n.getLeft(), entries);
            entries.addAll(n.getValues());
            listAll(n.getRight(), entries);
        }
    }

    @Override
    public int height() {
        return height(rootNode);
    }   

    //Custom Methods
    /**
     * A method to test if the tree is logically empty
     * 
     * @return true if empty, false if not
     */
    public boolean isEmpty() {
        return rootNode == null;
    }
    /**
     * Logically empties the tree by setting the rootNode to null
     */
    public void empty() {
        rootNode = null;
    }
    public void inOrderTraversal(Node node) {
        if(node != null) {
            inOrderTraversal(node.getLeft());
            System.out.print(node.getKey() + ", ");
            inOrderTraversal(node.getRight());
        }
    }
    public int height(Node node) {
        if(node == null) return -1;
        else return node.height;
    }
    public Node getRootNode() {
        return rootNode;
    }
    public Node smallestNode(Node node) {
        if(node.getLeft() == null)
            return node;
        return smallestNode(node.getLeft());
    }

    private Node rotateLeft(Node node2) {
        Node node1 = node2.getLeft();

        node2.setLeft(node1.getRight());
        node1.setRight(node2);

        node2.setHeight(Math.max(height(node2.getLeft()), height(node2.getRight())) + 1);
        node1.setHeight(Math.max(height(node1.getLeft()), node2.getHeight()) + 1);

        return node1;
    }
    private Node rotateRight(Node node1) {
        Node node2 = node1.getRight();

        node1.setRight(node2.getLeft());
        node2.setLeft(node1);

        node1.setHeight(Math.max(height(node1.getLeft()), height(node1.getRight())) + 1);
        node2.setHeight(Math.max(height(node2.getRight()), node1.getHeight()) + 1);

        return node2;
    }
    private Node doubleRotateLeft(Node node3) {
        node3.setLeft(rotateRight(node3.getLeft()));
        return rotateLeft(node3);
    }
    private Node doubleRotateRight(Node node1) {
        node1.setRight(rotateLeft(node1.getRight()));
        return rotateRight(node1);
    }
}
import java.util.Iterator;

public interface IAVLTree<K,V>
{
    public V add(K k, V v);

    public V remove(K k, V v);

    public Iterator<V> removeAll(K k);

    public Iterator<V> find(K k);

    public Iterator<V> listAll();

    public int height();

}
import java.util.ArrayList;
导入java.util.Comparator;
导入java.util.Iterator;
导入cw1.rs10.lib.IAVLTree;
公共类AVLTree实现了IAVLTree
{
公共类节点{
私钥;
私有数组列表值;
私有节点左、右;
私人内部高度;
公共节点(K键,V值){
this.key=key;
this.values=新的ArrayList();
this.left=null;
this.right=null;
这个高度=0;
增加(价值);
}
公共K getKey(){
返回键;
}
公共无效设置密钥(K密钥){
this.key=key;
}
公共ArrayList getValues(){
返回值;
}
公共无效附加值(V值){
增加(价值);
}
公共节点getLeft(){
左转;
}
公共节点getRight(){
返还权;
}
公共void setLeft(节点左侧){
this.left=左;
}
公共无效设置权限(节点权限){
这个。右=右;
}
公共整数getHeight(){
返回高度;
}
公共空间设置高度(内部高度){
高度=高度;
}
}
专用节点rootNode;
专用比较器;
//未使用
公共AVLTree(){
}
公共AVLTree(比较器-比较器){
this.rootNode=null;
这个比较器=比较器;
}
@凌驾
公共V添加(K,V){
节点n=rootNode=add(k,v,rootNode);
如果(n!=null)
返回v;
其他的
返回null;
}
专用节点添加(K键、V值、节点){
if(node==null)
返回新节点(键、值);
if(comparator.compare(key,node.getKey())<0){
setLeft(add(key,value,node.getLeft());
if(高度(node.getLeft())-height(node.getRight())==2){
if(comparator.compare(key,node.getLeft().getKey())<0)
节点=旋转英尺(节点);
其他的
节点=双旋转英尺(节点);
}
}else if(comparator.compare(key,node.getKey())>0){
node.setRight(添加(键、值、node.getRight());
if(高度(node.getRight())-height(node.getLeft())==2){
if(comparator.compare(key,node.getRight().getKey())>0)
节点=旋转右(节点);
其他的
节点=双旋转右(节点);
}
}否则{
//句柄重复
node.getValues().add(value);
}
setHeight(Math.max(height(node.getLeft())、height(node.getRight())+1);
返回节点;
}
@凌驾
公共V remove(K键,V值)引发异常{
Node=rootNode=remove(键、值、rootNode);
如果(节点!=null)
返回值;
其他的
返回null;
}
私有节点移除(K键、V值、节点){
//如果带有键的节点包含一个或更少的值,请删除整个键
//否则,请使用键从节点中删除值
如果(node==null)返回null;
else if(comparator.compare(key,node.getKey())<0){
setLeft(移除(键、值、node.getLeft());
if(高度(node.getLeft())-height(node.getRight())==2){
if(comparator.compare(key,node.getLeft().key)<0)
节点=旋转英尺(节点);
其他的
节点=双旋转英尺(节点);
}
}else if(comparator.compare(key,node.getKey())>0){
setRight(删除(键、值、node.getRight());
if(高度(node.getRight())-height(node.getLeft())==2){
if(comparator.compare(key,node.getRight().key)<0)
节点=旋转右(节点);
其他的
节点=双旋转右(节点);
}
}否则{
if(node.getValues().size()>1){
node.getValues().remove(值);
返回节点;
}否则{
if(node.getLeft()==null&&node.getRight()==null)
返回null;
if(node.getLeft()==null)返回node.getRight();
if(node.getRight()==null)返回node.getLeft();
Node smallestNode=smallestNode(Node.getRight());
节点=最小节点;
setRight(删除(键、值、node.getRight());
返回节点;
}
}
返回节点;
}
@凌驾
公共迭代器查找(K键){
节点n=搜索(键,根节点);
如果(n!=null){
ArrayList值=n.getValues();
返回值。迭代器();
}否则{
返回新的ArrayList().iterator();
}
}
专用节点搜索(K键,节点){
while(节点!=null){
if(comparator.compare(key,node.getKey())<0)
node=node.getLeft();
else if(comparator.compare(key,node.getKey())>0)
node=node.getRight();
其他的
返回节点;
}
返回null;
}
@凌驾
公共迭代器removeAll(K键){
节点n=搜索(键,根节点);
ArrayList值=n.getValues();
试一试{
删除(n.getKey(),null);
}捕获(例外e){
e、 printStackTrace
public class AVLTest
{
    private static long startTime, endTime;
    private static int amountOfCommands = 10000;

    public static void main(String[] args) {
        AVLTree<String, Integer> tree = new AVLTree<String, Integer>(String.CASE_INSENSITIVE_ORDER);
        try {
            startTime = System.currentTimeMillis();
            for (int i = 1; i <= amountOfCommands; i++) {
                String key = "K" + i;
                tree.add(key, i);
            }
            endTime = System.currentTimeMillis();
        } catch(Exception e) {
            e.printStackTrace();
        }
        long runningTime = endTime - startTime;
        System.out.println("Running Time: " + runningTime + "ms\nNo. of Commands: " + amountOfCommands);
    }
}
startTime = System.currentTimeMillis();
for (int i = 1; i <= amountOfCommands; i++) {
    String key = "K" + i;
    tree.add(key, i);
}
endTime = System.currentTimeMillis();
for (int i = 1; i < amountOfCommands; i++) { // note the < instead of <=
    String key = "K" + i;
    tree.add(key, i);
}
String key = "K" + amountOfCommands;
startTime = System.currentTimeMillis();
tree.add(key, amountOfCommands);
endTime = System.currentTimeMillis();