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的位置。

image-20210416100635682

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

image-20210416100810361

所以我们在计算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;
            }
        }
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值