Java TreeSet BigO的复杂性似乎已经消失

时间:2016-07-01 16:35:08

标签: java data-structures treeset

我相信Java TreeSet有一个平衡的树实现,可以快速执行树类排序(很像快速排序)。我最近遇到的问题表明它似乎正在进行我期望的更多比较。

每个平衡树在排序(插入)上是否像Java的TreeSet一样,或者我的性能测试方法是否错误?

我的代码:

package expri.johnny.treeSortCompTimes;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetCompTimeTest {
    public static void main(String[] args) {
        int size=1000;
        ArrayList<Integer> ay =new ArrayList<>(size);
        int treeHeight =   (int) (Math.log (size)/Math.log (2));
        System.out.println("tree height: "+treeHeight); 
        System.out.println("when size is "+ size + ",i expected compare tmies are: "+((treeHeight+1)*treeHeight/2)); 

        for(int i =0,l=size-1;i<=l;i++){
            ay.add(i);
        }


        Collections.shuffle(ay);
        System.out.println(ay);
        CountComp cc =new CountComp();
        TreeSet<Integer> ts =new TreeSet<>(cc);
        ts.addAll(ay);
        cc.speakCount();
    }

    private static class CountComp implements Comparator<Integer>{
        int counter =0;
        @Override
        public int compare(Integer o1, Integer o2) {
            this.counter++;
            int df = o1-o2;
            if(df>0){
                return 1;
            }else if(df==0){
                return 0;
            }else{
                return -1;
            }

        }
        public void speakCount(){
            System.out.println("total compared times: "+this.counter); 
            //when size is 100,i expected compare tmies are: 21 
                //total compared times: 545
            //when size is 1000,i expected compare tmies are: 45
                //however, the real total compared times: 8783
        }
    }
}

嗯,这就是我之前的想法:

10 compares for add
10 compares for add
10 compares for add
10 compares for add
10 compares for add
10 ...
10
10
10
10
10
10 -997th , what i thought was 7 
10 -998th  , what i thought  was 8 
10 - 999th , what i thought  was 9
10 - 1000th  , what i thought was 10 
8547
这次我笑了很多,哈哈哈!

2 个答案:

答案 0 :(得分:1)

当假设插入将使用log(n)比较时,您是正确的。 但是您插入了n元素,这些元素可以让我们进行n*log(n)比较。 对于1000个元素,它给我们9965比较。

n这里是元素的总数。

你的公式完全错了,我不知道你在哪里得到它。

答案 1 :(得分:1)

随着项目的添加,树的深度是动态的。要估计将要进行的比较次数,迭代要添加的元素的大小,并根据当时树的大小计算每个元素的比较次数。

int sum = 0;
for(int i = 1; i <= size; i++){
    sum += (int)Math.ceil(Math.log(i)/Math.log(2));
}
System.out.println(sum);

为1000个元素产生8987