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++]];
}
}
}