一、队列是什么?

队列queue:一种线性数据结构,队列中的元素只能先入先出(First In First Out,简称FIFO),队列的出口端叫作队头(front),队列的入口端叫作队尾(rear)。

队列这种数据结构本身是有序列表,既可以用数组来实现,也可以用链表来实现:

  如图:数组实现队列,队尾往往设置在最后一个元素的下一个位置。

队列的操作一般分为-------------入队和出队

---入队:把新元素放入队列中,只允许在队尾的位置放入元素,新元素的下一个位置将会成为新的队尾。

---出队:把元素移出队列,只允许在队头一侧移出元素,出队元素的后一个元素将会成为新的队头。

如下图 --------队列的入队和出队是分别从队列的前后端来处理,
    因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变。

二、单向队列怎么实现?

思路分析:入队和出队

  入队:a. 当 front == rear【空】,将尾指针往后移:rear+1。

     b. 指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。rear==maxSize-1[队列满]

//定义队列的基本组成
private int maxSize; //表示数组的最大容量
private int front; //队头指针
private int rear; //队尾指针
private int[] arr;
//创建队列构造器
public ArrayQueue(int arrMaxSize) {
  this.maxSize = arrMaxSize;
  this.front = -1;//指向队列头部的之前的位置,没有任何数据时,指向虚无
  this.rear = -1;//指向队列尾部的位置,最后一个元素的位置
  this.arr = new int[this.maxSize];
}
//判断队列是否满了
public boolean isFull() {
  //(rear+1)%array.length == front)
  return rear == maxSize;
}
//判断队列是否为空
public boolean isEmpty() {
  return rear == front;
}
//添加数据到队列
public void addQueue(int element) {
  if(isFull()) {
  System.out.println("队列已满");
  return ;
  }
  rear++;
  arr[rear] = element;
}
//获取队列值,出队列
public int getQueue() {
  //判断是否为空
  if(isEmpty()) {
  throw new RuntimeException("队列为空");
  }
  front++;

       int value = arr[front];
       return value;

}
//显示队列的所有数据
public void showQueue() {
  //遍历
  if(isEmpty()) {
  System.out.println("队列为空,遍历个锤子");
}
for(int i=0; i < arr.length; i++) {
  System.out.printf("arr[%d]=%d\n",i,arr[i]);
  }
}
//实现队列头部
public int headQueue() {
  if(isEmpty()) {
  System.out.println("队列为空,没有头");
  }
  return arr[front+1];
}

缺陷:数组无法复用,造成空间浪费。

三、环形队列怎么实现?

//注意环形队列最大实际有效值为 最大值-1,因为需要空余一个数组位,用于作变动,让数组尾指针重新指回数组的首位(取模之法)

//定义队列的基本机构

private int maxSize;   //表示数组的最大容量

private int front;    //队头指针,队列的第一个元素,初始值为0

private int rear;     //队尾指针,队列最后一个元素的后一个位置,初始值为0

private int[] arr;

//创建队列构造器

public CirQueue(int arrMaxSize) {

  this.maxSize = arrMaxSize;

  this.arr = new int[this.maxSize];

}

//判断队列是否满了

public boolean isFull() {

  //(rear+1)%array.length == front)

  return (rear+1)%maxSize == front;

}

//判断队列是否为空

public boolean isEmpty() {

  return rear == front;

}

//添加数据到队列

public void addQueue(int element) {

  if(isFull()) {

  System.out.println("队列已满");

  return ;

  }

  //将元素加入队列

  arr[rear] = element;

  //rear 后移,这里必须考虑取模---把尾指针定位到数组开始位置,循环利用数组

  rear = (rear + 1) % maxSize;

}

//获取队列值,出队列

public int getQueue() {

  //判断是否为空

  if(isEmpty()) {

  throw new RuntimeException("队列为空");

}

  //这里需要分析出front是指向队列的第一个元素

  //1.先把front对应的值保留到一个临时变量

  //2.将front后移-----考虑取模

  //3.将临时保存的变量返回

  int value = arr[front];

  front=(front+1)%maxSize;

  return value;

}

//显示队列的所有数据

public void showQueue() {

  //遍历

  if(isEmpty()) {

  System.out.println("队列为空,遍历个锤子");

  return;

  }

  

      //输出---队列---遍历
      //从哪里开始遍历,到哪里结束呢?----头指针在哪,就从那个开始
      //得到环形数组中具有多少个元素。-----当前队列的有效元素具体--(rear + maxSize - front) % maxSize
      //从头指针 开始

  for(int i=front; i < front+size(); i++) {

  System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i % maxSize ]);

  }

}

//求出当前队列有效数据的个数

public int size() {

  return (rear + maxSize - front) % maxSize;

}

//实现队列头部

public int headQueue() {

  if(isEmpty()) {

  System.out.println("队列为空,没有头");

  }

  return arr[front+1];

}

 方法二:

private int[] array;
private
int front;
private int rear;
//环形队列构造器
public MyQueue(int capacity){
  
this.array = new int[capacity];
}
//入队
public void enQueue(int element) throws Exception {
  if((rear+1)%array.length == front){
      throw new Exception(" 队列已满!");
   }
    array[rear] = element;
    rear =(rear+1)%array.length; }
//出队
public int deQueue() throws Exception {
  if(rear == front){
    throw new Exception(" 队列已空!");
}
  int deQueueElement = array[front];
  front =(front+1)%array.length;
  return deQueueElement;
}
//输出---队列---遍历
public void output(){
for(int i=front; i!=rear; i=(i+1)%array.length){
   System.out.println(array[i]);
  }
}
//此法来源于---漫画算法:小灰的算法之旅 
01-14 12:01