1. 题目描述
2. bug原因
因为是个模板题,所以我做的比较轻松,就用数组模拟队列,但因为 spfa 入队出队十分频繁,因此需要用循环队列,我是这么模拟循环队列的:
int q[N];
int hh = 0, tt = 0;
while(hh != tt) // not empty
{
int t = q[hh]; // out queue
hh = (hh + 1) %N;
...
int j;
...
tt = (tt + 1) % N;
q[tt] = j;
}
可以发现,我只是在模拟普通队列的基础上加上了取模操作,看起来没什么问题,其实问题大大的!因为这么写无法判断队列什么时候为空!具体的我就不详细说了!
3. 解释
普通队列
int q[N];
int hh = 0, tt = -1;
while(hh <= tt) // not empty
{
int t = q[ hh ++ ]; // out queue
...
int j;
...
q[ ++ tt ] = j; // 入队
}
注意,这种将
hh=0;tt=-1;
形式的队列,无法设计为循环队列,因为我们无法判断队空。在初始时,
hh>tt
,对空,但因为循环队列的缘故,tt
可能跑到hh
的前面。
有错误的循环队列
int q[N];
int hh = 0, tt = 0;
while(hh != tt) // not empty
{
int t = q[hh]; // out queue
hh = (hh + 1) %N;
...
int j;
...
tt = (tt + 1) % N;
q[tt] = j;
}
在这种写法下,初始状态下,
hh==tt
,队列为空,当tt
跑到hh
前面时,判断条件仍然如此。但是这种情况有一个bug,就是当队满的时候,也是
hh==tt
但是在竞赛中,我们一般将数组开的比较大,因此一般不会出现队满的情况。
不过我们要了解,如果处理该问题。
常见的解决办法是安插一个空位置,用来处理队空和队满的情况。
在安插一个空位置后,队空:
hh==tt;
队满:
(tt + 1) % N = hh;
Length:
(tt - hh + N) % N;
(因为 tt - hh 可能为负数,因此需 + N)
N
是队列的大小(包含空位置)
正宗循环队列(带一个空位置)
// N = q.capacity()
int q[N];
int hh = 0, tt = 0;
bool isEmpty()
{
return hh == tt;
}
bool isFull()
{
return (tt + 1) % N == hh;
}
size_t length()
{
return (tt - hh + N) % N;
}
void push(int val)
{
assert(isEmpty());
q[tt ++ ] = val;
tt %= N;
}
void pop()
{
assert(!isEmpty());
q[hh ++ ];
hh %= N;
}
标签:...,队列,--,tt,int,hh,bug,AcWing852
From: https://www.cnblogs.com/ALaterStart/p/17179008.html