持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情。
循环队列
在上一篇中,我们利用了%(除余)实现了队列指针循环移动。但这样的循环链表仍存在缺陷,不足以满足我们的要求。
public class queueArr{
int[] arr;
int headIndex;
int endIndex;
public void add(int value) // 队列添加方法
{
endIndex = ++ endIndex % this.arr.length;
if(endIndex == headIndex)
{
endIndex--;
System.out.println("这个队列已经满了哦");
return;
}
arr[endIndex] = value;
}
public int pop() // 队列取出方法
{
headIndex = ++headIndex % this.arr.length;
if(headIndex == endIndex)
{
headIndex--;
System.out.println("你不能从一个空队列中取出元素");
return;
}
return arr[headIndex];
}
}
这个队列的尾指针始终指向队尾的最后一个元素,头指针则始终指向当前队列中最"老"的元素的前一个位置,而在我们的add()和pop()方法中,是通过判断下一个节点是不是头节点/尾节点来确定当前队列为满/空。这样的判断方法会有个问题,当我们只剩下一个元素时,队列就无法再取出元素了。这会导致队列始终有一个元素取不出来。
所以我们要重新处理判定方法,会出现这个问题的首要原因是:尾指针是指向新元素的,而头指针是指向旧元素的前一个位置的,我们在两个方法中判定满和空的条件是头尾指针移动后是否会与另一方重合。
基于顺序表实现的循环队列就会有这么个问题:当头尾指针重合时,我们很难判断此时队列到底是空还是满。 我们可以新设立一个属性length,每当有元素入队时令length+1,当有元素出队时令length-1。然后我们之只要通过判断length的值就可以很轻松地确定当前队列到底是空还是满。
public void add(int value)
{
if(length == this.arr.length)
{
System.out.println("这个队列已经满了哦");
return;
}
arr[++endIndex] = value;
}
public int pop()
{
if(length == 0)
{
System.out.println("你不能从一个空队列中取出元素");
return null;
}
return arr[++headIndex];
}
现在我们的循环队列就能够正常使用了。
小结
本篇我们总结了分析了构建出的循环链表中存在的缺陷,并将其完善了。
天天学习,加速成长!
希望与各位一起变得越来越强!