《算法》习题1.3.35-1.3.36两个题一块凑一个RandomQueue的api的实现

闲话不说,先上题截图:

 就是要实现图中要求的若干个api接口。有这么几个点,一个是要数组实现,如果发现数组不够用了,要扩容;第二个dequeue不是获取队列头的元素,而是获取尾部元素,这就相对简单,难点在要随机获取一个数,然后与尾部元素互换。如果没有这一条要求,通常从头部出队列的话,还有个数组循环利用的问题,就是指针取数组元素的模,然后用模来指向位置。迭代器的特点是随机获取元素,实现iterator接口的.next()方法的时候,要思考怎么实现随机获取。

1、首先来看看怎么设置成员变量

public class RandomQueue<Item> implements Iterable<Item> {
    private Item[] array;
    private Item item;
    private int index;
    private int arraysize; //
    //构造方法
    public RandomQueue(){
        this(10);
        this.arraysize = 10;
        this.index = 0;
    }
    public RandomQueue(int capacity){
        this.array = (Item[])new Object[capacity];
        this.arraysize = capacity;
        this.index = 0;
    }

首先支持泛型类型。由于本题只在尾部进出元素,所以只考虑一个指针变量index,指向最后一个元素的后一位。数组的大小用arraysize,这里是创立的数组大小,要比数组的长度大,不是一个概念。然后是重载两个构造方法,一个是有初始容量的,一个是无参构造。构造函数里面设置index=0,一开始index指向array[0]。

二、是否为空以及数组扩容

//是否为空
    public boolean isEmpty(){
        return index == 0;
    }
    private void incr_size(){
        this.arraysize = 2 * arraysize;
        Item [] new_array = (Item[])(new Object[arraysize]);
        for (int i=0; i<index; i++) { new_array[i] = this.array[i]; }
        this.array = new_array;
    }

isEmpty,如果index = 0 的话,表明数组中没有元素,所以回到条件index == 0;扩容的话,简单变为2倍,然后把老的数组拷贝到新的数组。对象成员变量变成新的数组。

三、入列和出列

//入列
    public void enqueue(Item item){
        if(index == arraysize - 1) this.incr_size();
        this.array[index] = item;
        this.index++;
    }
    //出列
    public Item dequeue(){
        Item element = null;
        Item temp = null;
        Random random = new Random();
        if(index > 1){
            int num = random.nextInt(index - 1);
            temp = array[index - 1];
            array[index - 1] = array[num];
            array[num] = temp;
        }
        element = array[index-1];
        this.index--;
        return element;
    }

入列需要判断index是否只比arraysize小1,如果是,就要扩容。

出列的话,需要构建一个随机对象,然后获取随机的int数,然后进行数的交换,然后把指针往前移一位,回到出列的元素。

四、获取元素个数和sample接口

 int get_length(){ return index; }
    Item sample(){
        Item element = null;
        Random random = new Random();
        if(index >= 1){
            int num = random.nextInt(index - 1);
            element = array[num];
        }
        return element;
    }

sample接口也是要通过随机数来获取。

五、难点:迭代器实现

迭代器的话主要是要实现两个方法,一个是 hasNext,字面意思就是还有没有下一个?另一个就是next方法,如果有下一个,那么下一个是谁。
 

@Override
    public Iterator<Item> iterator() {
        return new RandomQueueIterator();
    }
    private class RandomQueueIterator implements Iterator<Item>{
        private  int size = index;
        private RandomQueue numqueue;
        public RandomQueueIterator(){
            numqueue = new RandomQueue();
            for(int i = 0 ; i < index ; i ++) {
                numqueue.enqueue(i);
            }
        }
        @Override
        public boolean hasNext() {

            return size-- >= 1;
        }

        @Override
        public Item next() {
            int num = (int)numqueue.dequeue();

            Item element = array[num];

            return element;
        }
    }

因为next方法是要随机遍历,所以难点在于怎么不重复的获取随机数,所以想到本身RandomQueue有一个随机dequeue方法,可以随机出列元素。因此在内部类中构造一个RandomQueue的对象numqueue,利用这个对象的dequeue方法获取对应的数组下标。这里不能把对象的创建放到next方法里面,因为会循环调用next方法,如果放在里面,就会重复创建numqueue对象,就不合适了。

六、测试即结果

public static void main(String[] args) {
        RandomQueue<Integer> randomQueue = new RandomQueue<>();

        for(int i = 0 ; i < 15 ;i ++) {
            randomQueue.enqueue(i);
        }
        for(int j: randomQueue) {

            System.out.print(j +" ");
        }
        System.out.println();
       for(int i = 0 ; i<15 ; i++)
            System.out.print(randomQueue.dequeue()+ " ");


    }



10 14 0 4 5 7 13 1 9 12 3 2 8 11 6 
7 12 14 5 6 4 0 11 2 9 10 8 1 3 13 

foreach实现随机迭代。结果和dequeue类似。证明测试是基本成功的。

这里仅仅为做题需要,代码的完备性不足。特此提示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值