题目
随机队列。随机队列能够存储一族元素并支持表1.3.11中的API:
public class RandomQueue<Item> | |
---|---|
RandomQueue() | 创建一条空的随机队列 |
boolean isEmpty() | 队列是否为空 |
void enqueue(Item item) | 添加一个元素 |
Item dequeue() | 删除并随机返回一个元素(取样且不放回) |
Item sample() | 随机返回一个元素但不删除它(取样且放回) |
编写一个RandoQueue类来实现这份API。提示:使用(能够动态调整大小的)数组表示数据。删除一个元素时,随机交换某个元素(索引在0和N-1之间)和末尾元素(索引为N-1)的位置,然后像ResizingArrarStack一样删除并返回末位元素。编写一个用例,使用RandomQueue<Card>在桥牌中发牌(每人13张)。
思路
随机取一个0到N-1之间的值来模拟发牌,并把末尾元素补充到抽出的位置。
代码
package Chap1.$3;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdRandom;
import java.util.Iterator;
public class E35<Item> implements Iterable<Item>
{
private static int N = 0;
private Item[] a = (Item[]) new Object[1];
public boolean isEmpty()
{
return N == 0;
}
public int size()
{
return N;
}
public void resize(int max)
{
Item[] temp = (Item[]) new Object[max];
int j = 0;
for (int i = 0; i < N; i++)
temp[j++] = a[i];
a = temp;
}
public void enqueue(Item item)
{
if (N == a.length) resize(a.length * 2);
a[N++] = item;
}
public Item dequeue()
{
int n = StdRandom.uniform(N);
Item temp = a[n];
a[n] = a[--N];
if (N == a.length / 4) resize(a.length / 2);
return temp;
}
public Item sample()
{
int n = StdRandom.uniform(N);
return a[n];
}
public static void main(String[] args)
{
E35<Integer> e = new E35<Integer>();
for (int i = 1; i < 14; i++)
{
e.enqueue(i);
}
int maxsize = e.size();
Iterator<Integer> iterator = e.iterator();
while (iterator.hasNext()) System.out.print(iterator.next() + " ");
System.out.println();
for (int i = 0; i < maxsize; i++)
System.out.print(e.dequeue() + " ");
}
public Iterator<Item> iterator()
{
return new ArraryIterator();
}
public class ArraryIterator implements Iterator<Item>
{
private int i = N;
public boolean hasNext()
{
return i > 0;
}
public Item next()
{
int n = StdRandom.uniform(i);
Item temp = a[n];
a[n] = a[--i];
return temp;
}
public void remove()
{
}
}
}
注意
解答中用Integer代替Card;main函数中一个迭代器输出,一个for循环输出,每次只能用一个,不然第一个会打乱数组,导致第二个输出错误。