1.3.35 #
解答 #
事实上只需要在普通队列的基础上稍作修改就可以了。
出队时先随机选择一个元素,之后让它和最开始的元素做交换,之后正常出队即可。
代码 #
RandomQueue.cs #
/// <summary>
/// 随机队列。
/// </summary>
/// <typeparam name="TItem">队列中要存放的元素。</typeparam>
public class RandomQueue<TItem>
{
private TItem[] _queue;
private int _count;
/// <summary>
/// 新建一个随机队列。
/// </summary>
public RandomQueue()
{
_queue = new TItem[2];
_count = 0;
}
/// <summary>
/// 判断队列是否为空。
/// </summary>
/// <returns></returns>
public bool IsEmpty()
{
return _count == 0;
}
/// <summary>
/// 为队列重新分配内存空间。
/// </summary>
/// <param name="capacity"></param>
private void Resize(int capacity)
{
if (capacity <= 0)
{
throw new ArgumentException();
}
var temp = new TItem[capacity];
for (var i = 0; i < _count; i++)
{
temp[i] = _queue[i];
}
_queue = temp;
}
/// <summary>
/// 向队列中添加一个元素。
/// </summary>
/// <param name="item">要向队列中添加的元素。</param>
public void Enqueue(TItem item)
{
if (_queue.Length == _count)
{
Resize(_count * 2);
}
_queue[_count] = item;
_count++;
}
/// <summary>
/// 从队列中随机删除并返回一个元素。
/// </summary>
/// <returns></returns>
public TItem Dequeue()
{
if (IsEmpty())
{
throw new InvalidOperationException();
}
var random = new Random(DateTime.Now.Millisecond);
var index = random.Next(_count);
var temp = _queue[index];
_queue[index] = _queue[_count - 1];
_queue[_count - 1] = temp;
_count--;
if (_count < _queue.Length / 4)
{
Resize(_queue.Length / 2);
}
return temp;
}
/// <summary>
/// 随机返回一个队列中的元素。
/// </summary>
/// <returns></returns>
public TItem Sample()
{
if (IsEmpty())
{
throw new InvalidOperationException();
}
var random = new Random();
var index = random.Next(_count);
return _queue[index];
}
}