Java AVL树给我O(c^n)而不是O(logn)
我已经用java创建了一个AVLTree,add方法应该是O(logn)。。。然而,我的add方法似乎给了我一个O(c^n)图或指数图,而不是对数图。以下是运行时间与输入大小的关系图: 有人能帮忙弄清楚为什么会发生这种情况吗 以下是我的AVLTree的代码: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
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();