问题描述:循环队列为空条件是 rear=front 。如果进队元素的速度快于出队元素的速度,队尾指针很快就赶上了队首指针,此时可以看出循环队列的队满条件也为 rear=front。怎样区分这两者之间的差别呢?
解决方案:
方法一:把数组的前端和后端连接起来,形成一个循环的顺序表,即把存储队列元素的表从逻辑上看成一个环。循环队列的队头指针和队尾指针初始化时都置0,队满条件:(rear+1)%MaxSize=front,队空条件:rear=front。
方法二:用一个标志tag标识队列可能空(0)或可能满(1),加上front==rear作为队满或队空的条件。Tag初始值置为0,每当入队成功,tag=1,每当出队成功,tag=0。当front=rear&&tag=1时,表示在入队操作后front=rear,此时队满,同理,front=rear&&tag=0时则表示队空。
代码实现:
namespace ConsoleApplication
{
class sqQueueClass
{
const int MaxSize = 100;
public string[] data;
public int front, rear;
public int tag = 0;
public sqQueueClass()
{
data = new string[MaxSize];
front = rear = -1;
}
public bool QueueEmpty()
{
return (front == rear && tag == 0);
}
public bool enQueue(string e)
{
if (front == rear && tag == 1)
return false;
rear = (rear + 1) % MaxSize;
data[rear] = e;
tag = 1;
return true;
}
public bool deQueue(ref string e)
{
if (front == rear && tag == 0)
return false;
front = (front + 1) % MaxSize;
e = data[front];
tag = 0;
return true;
}
}
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
sqQueueClass L1 = new sqQueueClass();
bool pandan = false;
pandan = L1.enQueue("3");
Console.WriteLine(pandan);
pandan = L1.enQueue("5");
Console.WriteLine(pandan);
pandan = L1.enQueue("8");
Console.WriteLine(pandan);
pandan = L1.enQueue("4");
Console.WriteLine(pandan);
pandan = L1.enQueue("0");
Console.WriteLine(pandan);
string e = "";
pandan = L1.deQueue(ref e);
Console.WriteLine(pandan);
Console.WriteLine(e);
Console.ReadKey();
}
}
}
运行结果如图示:
比较:方法一判断条件较为简单,但浪费了一个存储空间;方法二能够充分利用存储空间,但在进行出队入队操作时,每次都需要对tag进行重新定义且判断条件较为复杂。
总结:循环队列在实现入队出队操作时,应注意算法实现顺序,入队时先判断是不是队满,出队时先判断是不是队空,然后再进行相应的入队出队操作。