随机背包---存储一组元素并进行随机访问

背包可以存储一组数据,随机背包要求每次迭代,所有N!种排列出现的概率相等。

方法:

用数组保存一组元素,并在迭代器中的构造函数中随机打乱他们的顺序:
此时的打乱并非将原数组中的元素重新排列,而是使用一个新数组存储打乱的下标,并用新数组元素的顺序去遍历原数组

支持如下API

1.RandomBag()
2.isEmpty()
3.size()
4.add(Item item)

代码
import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;

/**
 * @author 鯉伴MAY
 * @param <Item>
 */
public class RandomBag<Item> implements Iterable<Item> {
    private Item[] array;
    private int N;
    public RandomBag(){
        array = (Item[]) new Object[1];
    }

    private void resize(int max){
        Item[] temp = (Item[]) new Object[max];
        for (int i = 0; i < N; i++) {
            temp[i] = array[i];
        }
        array = temp;
    }
    public void add(Item item) {
        if(N == array.length)
            resize(2*array.length);
        array[N++] = item;
    }

    public boolean isEmpty() {
        return  N==0;
    }

    public int size(){
        return  N;
    }
    @Override
    public Iterator<Item> iterator() {
        return new BagIterator();
    }

    private class BagIterator implements Iterator {
        //使用一个数组记录打乱的下标,以打乱的下标去访问原数组,实现快速随机访问
        private int[] seq = new int[N];
        private int index = 0;
        public BagIterator() {
            for(int i=0;i<N;i++) {
                seq[i] =i;
            }
            StdRandom.shuffle(seq);
            /*
            此函数的源码如下:
            public static void shuffle(int[] a) {
                validateNotNull(a);
                int n = a.length;
                //此函数遍历数组,使每一个元素都随机和另一个交换为位置
                //此方法何以保证每个新的迭代器得到N!种排列出现的可能性相等
                for (int i = 0; i < n; i++) {
                    int r = i + uniform(n-i);     // between i and n-1
                    int temp = a[i];
                    a[i] = a[r];
                    a[r] = temp;
                }
            }
            //返回0-n之间的随机一个正整数
            public static int uniform(int n) {
                if (n <= 0) throw new IllegalArgumentException("argument must be positive: " + n);
                return random.nextInt(n);
            }
             */
        }
        @Override
        public boolean hasNext() {
            return index<N;
        }

        @Override
        public Object next() {
            return array[seq[index++]];
        }
    }
}
posted @ 2019-10-15 20:59  dwwzone  阅读(156)  评论(0编辑  收藏  举报