对于队列来说,它新加入了一套新的指针即rear和front指针,对于这两个指针,我们需要明确的是各自的功能以及移动需要规避的问题。
队列基本规则:先进先出,后进后出,从头进,从尾入。
1.顺序队列(循环队列)判断空的条件和判断队满的条件
队 满 :(rear+1)%data.length==front;
队 空:front == rear;
2.循环队列的模运算
我们小学数学中的求余数,余数一定要比除数小。在循环队列中,我们以此记录数据。例如,我们记录循环队列长度,我们就只需要将(rear - front +data.length)%data.length,这是为了防止队列的溢出,使数据永远保持在一个[0,data.length]的区间范围内。
3.栈顶指针与rear,front的区别
这是一个很笼统的问题,其实,栈顶指针是双向的,无论入栈或者出栈,必须栈顶指针参与,并且只需栈顶指针的移动。队的指针不一样的是rear永远指向队头,front永远指向队尾,遵循队列的基本规则不变。
- 顺序循环队列实现
-
public class sequeceQueue { private int front,rear; final int Maxsize = 10; private Object[] data; //队列初始化 public sequeceQueue() { front = rear = 0; data = new Object[Maxsize]; } public void Enqueue(Object x) { //如果队列满了,就扩容 if(isfull()) { Object[] temp = new Object[2*data.length]; for (int i = 0; i < temp.length; i++) { temp[i] = data[(i+front)%data.length]; } data = temp; } //2.添加在元素的末尾,其中rear位置后移并且不能超过size() rear = (rear+1)%data.length; //3.扩容之后,在尾部添加元素 data[rear] = x; } public Object Dequeue() { if(isEmpty()) { System.out.println("队列为空,无法出队"); return null; } //当从队列删除元素时,头部指针往后移动 //头front位应往后以步长=1移动,取模,不可超过size() front = (front+1)%data.length; return data[front]; } //循环队列中,判断是否为空,是否溢出,需要相应的模运算 public boolean isfull() { return (rear+1)%data.length==front; } public boolean isEmpty() { return front == rear; } public int size() { return (rear - front +data.length)%data.length; } public void print() { int i,j= front; for (i=1;i<=size();i++) { j = (j+1)%data.length; System.out.print(data[j] +" "); } System.out.println(""); } public Object getTop() { if(isEmpty()) { System.out.println("队列为空,无法出队"); return null; } return data[(front+1)%data.length]; } public static void main(String[] args) { sequeceQueue sq = new sequeceQueue(); int[] a = {3,4,4,3,2,5}; for (int i = 0; i < a.length; i++) { sq.Enqueue(a[i]);//入队 } sq.print(); sq.Dequeue();//出队 sq.print(); } }
-
链队实现
public class linkqueue { private int length; private Node front,rear; public linkqueue() { length = 0; front = rear = new Node(null);//有头结点的链表 } public boolean isEmpty() { if(front.next==null){return false;} return false; } public void enqueue(int x) { //队列是从后面增加,直接在尾结点添加一个新的节点 //分两种情况考虑。 Node newnode = new Node(x); if (front.next == null) { front.next =newnode; } /* * front -->1-->2-->3-->4-->5(rear)-->newnode(rear.next) * 入队:(rear.next=newnode) * front -->1-->2-->3-->4-->5-->6(rear) * 结束:(rear=newnode) */ rear.next = newnode; rear = newnode; length++; } public int dequeue() { //队列的出队是出第一个,下一个指向前一个就行 Node p = front.next; int x = p.date; /* p p.next * (front)-->1-->2-->3-->4-->5(rear) * 出队:(头指针指向p的下一位) * (front)-->2-->3-->4-->5(rear) */ p = p.next; length--; if(front.next==null) { rear= front; } return x; } public int size() { return length; } public int getHead() { return front.next.date; } public void print() { Node p = front.next; while(p!=null) { System.out.print(p.date+" "); p= p.next; } System.out.println(""); } public void clear() { front.next=rear.next=null; } public static void main(String[] args) { linkqueue lq = new linkqueue(); int a[] = {1,2,3,4,5,6,7}; lq.enqueue(9); lq.enqueue(8); lq.enqueue(5); for (int i = 0; i < a.length; i++) { lq.enqueue(a[i]); } lq.print(); System.out.println(lq.dequeue()); } }