随机队列

public class RandomQueue< Item >
随机队列能够存储一组元素并支持如下API
RandomQueue() 创建一个空队列
isEmpty()判断队列是否为空
enqueue(Item item) 添加一个元素
dequeue()删除并返回一个随机元素
sample() 随机返回一个元素,不删除

方法

1.使用动态数组存储数据
2.删除元素时,随机交换某个元素和末尾元素的位置,然后删除并返回末尾元素
3.编写随机迭代器,随机返回队列中的所有元素

代码

import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
import java.util.Random;

/**
 * @author 鯉伴MAY
 * @param <Item>
 */
public class RandomQueue<Item> implements Iterable<Item>{
    private Item[] array;
    private int N;


    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 RandomQueue() {
        array = (Item[]) new Object[1];
        N = 0;
    }
    public boolean isEmpty() {
        return N==0;
    }

    public void enqueue(Item item){
        if(N == array.length) {
            resize(2*N);
        }
        array[N++] = item;
    }

    //随机返回一个元素 并删除
    public Item dequeue() {
        if(N==0){
            System.out.println("队列已空");
            return null;
        }
        Random random = new Random();
        int index = random.nextInt(N);//返回0到N-1之间的一个随机整数
        //交换array[N-1]和array[index]的值
        Item temp = array[N-1];
        array[N-1] = array[index];
        array[index] = temp;
        temp = array[--N];
        array[N] = null;//置空,避免对象游离
        if(N>0 && N == array.length/4)
            resize(array.length/2);
        return temp;
    }

    //随机返回一个元素但是不删除
    public Item sample() {
        if(N==0){
            System.out.println("队列已空");
            return null;
        }
        Random random = new Random();
        int index = random.nextInt(N);//返回0到N-1之间的一个随机整数
        return array[index];
    }

    @Override
    public Iterator<Item> iterator() {
        return new  RandomQueueIterator();
    }

    private class RandomQueueIterator implements Iterator {

        //使用一个数组记录打乱的下标,以打乱的下标去访问原数组,实现快速随机访问
        private int[] seq = new int[N];
        private int index = 0;
        public RandomQueueIterator() {
            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-16 19:55  dwwzone  阅读(546)  评论(0编辑  收藏  举报