cs61b实验记录(五)HW3、Lab10

cs61b实验记录(五)HW3、Lab10

HW3

equals

@Override
    public boolean equals(Object o) {
        if (o==this)return true;
        if (o==null)return false;
        if (o instanceof SimpleOomage){
            SimpleOomage anothero=(SimpleOomage)o;
            return this.red==anothero.red&&this.blue==anothero.blue&&this.green==anothero.green;
        }return false;
    }

testHashCodePerfect

之前的hashcode方法:return red + green + blue;

这样会导致很多不必要的碰撞,two SimpleOomages may only have the same hashCode only if they have the exact same red, green, and blue values

fill in the testHashCodePerfect of TestSimpleOomage with code that tests to see if the hashCode function is perfect.

直接判断两个颜色不同的对象的hashCode是否相同

@Test
    public void testHashCodePerfect() {
        SimpleOomage ooA = new SimpleOomage(20, 10, 55);
        SimpleOomage ooA2 = new SimpleOomage(10, 20, 55);
        SimpleOomage ooA3 = new SimpleOomage(20, 10, 55);
        assertNotEquals(ooA.hashCode(),ooA2.hashCode());
        assertEquals(ooA.hashCode(),ooA3.hashCode());
    }

A Perfect hashCode

@Override
    public int hashCode() {
        if (!USE_PERFECT_HASH) {
            return red + green + blue;
        } else {
            return 61*(61*(red*61+green)+blue);
        }
    }

haveNiceHashCodeSpread

判断hashCode是否均匀散列,减少不必要的碰撞

public static boolean haveNiceHashCodeSpread(List<Oomage> oomages, int M) {

        int[] buckets=new int [M];
        for (Oomage o:oomages){
            int bucketNum = (o.hashCode() & 0x7FFFFFFF) % M;
            buckets[bucketNum]++;
            if (buckets[bucketNum]>=oomages.size()/2.5){
                return false;
            }
        }
        for (int i=0;i<buckets.length;i++){
            if (buckets[i]<=oomages.size()/50.0)
                return false;
        }
        return true;
    }

Evaluating the perfect hashCode Visually

因为red,blue,green都是5的倍数,通过之前的hashCode方法,不管怎么算,得到的hashCode永远是5的倍数。而由于bucketNum的计算方法是将hashCode对bucket的数量求余,所以如果bucket的数量不是5的倍数,那么就可以均匀散列,但是如果bucket的数量是5的倍数,比如10,那么结果就会集中在5和0的位置。

cs61b实验记录(五)HW3、Lab10

如果将bucket的数量改为9,就可以均匀散列

cs61b实验记录(五)HW3、Lab10

所以我们在计算hashCode前,需要将red、blue、green的值除以5,再计算。

@Override
    public int hashCode() {
        if (!USE_PERFECT_HASH) {
            return red + green + blue;
        } else {
            return 61*(61*(61*red/5+green/5)+blue/5);
        }
    }

Evaluating the ComplexOomage hashCode

对于ComplexOomage,它有一个Integer的List,它的hashCode计算方法是将这个List中的每个数乘以256后和下一个数相加,再乘以256 。

 @Override
    public int hashCode() {
        int total = 0;
        for (int x : params) {
            total = total * 256;
            total = total + x;
        }
        return total;
    }

256是1后面跟8个0,而int的表示范围是1后面跟32个0,所以最多乘四次就会溢出。所以hashCode的结果取决于ComplexOomage的List中的最后四个数。

我们只需要将每一个ComplexOomage对象的List中的最后四个数设置为相同的就可以实现testWithDeadlyParams

@Test
    public void testWithDeadlyParams() {
        List<Oomage> deadlyList = new ArrayList<>();
        int deadlyListSize=10000;
        for (int i=0;i<deadlyListSize;i++){
            int N = StdRandom.uniform(1, 10);
            ArrayList<Integer> params = new ArrayList<>(N);
            for (int j = 0; j < N - 4; j += 1) {
                params.add(StdRandom.uniform(0, 255));
            }
            for (int j = N - 4; j < N; j++) {
                params.add(1);
            }
            deadlyList.add(new ComplexOomage(params));
        }
        assertTrue(OomageTestUtility.haveNiceHashCodeSpread(deadlyList, 10));
    }

Lab 10

private static int leftIndex(int i) {
        return i * 2;
    }

    /**
     * Returns the index of the node to the right of the node at i.
     */
    private static int rightIndex(int i) {
        return i * 2 + 1;
    }

    /**
     * Returns the index of the node that is the parent of the node at i.
     */
    private static int parentIndex(int i) {
        return i / 2;
    }
/**
     * Bubbles up the node currently at the given index.
     */
    private void swim(int index) {
        // Throws an exception if index is invalid. DON'T CHANGE THIS LINE.
        validateSinkSwimArg(index);
        if (index > 1 && contents[index].myPriority < contents[index / 2].myPriority) {
            swap(index, index / 2);
            swim(index / 2);
        }
    }

    /**
     * Bubbles down the node currently at the given index.
     */
    private void sink(int index) {
        // Throws an exception if index is invalid. DON'T CHANGE THIS LINE.
        validateSinkSwimArg(index);
        if (index*2<=size){
            int j=index*2;
            if (j+1<=size&&contents[j+1].myPriority<contents[j].myPriority) j++;
            if (contents[j].myPriority>=contents[index].myPriority) return;
            sink(j);
        }
    }
@Override
    public void insert(T item, double priority) {
        /* If the array is totally full, resize. */
        if (size + 1 == contents.length) {
            resize(contents.length * 2);
        }
        contents[size+1]=new Node(item, priority);
        size++;
        if (size>=2)
            swim(size);
    }
public T removeMin() {
        T min=contents[1].myItem;
        swap(1, size);
        contents[size]=null;
        size--;
        sink(1);
        return min;
    }
@Override
    public void changePriority(T item, double priority) {
        for (int i=1;i<=size;i++){
            if (contents[i].myItem.equals(item)){
                double temp=contents[i].myPriority;
                contents[i].myPriority=priority;
                if (temp>priority) swim(i);
                else sink(i);
                return;
            }
        }
    }
上一篇:vue换肤


下一篇:CSS3学习笔记——常用选择器