队列介绍


1) 队列是一个有序列表,可以用数组或是链表来实现
2) 遵循先入先出(FIFO)的原则。即:先存入队列的数据,要先取出。后存入的要后取出
3) 示意图:(使用数组模拟队列示意图)

    

 

 

 


 

数组模拟队列思路

  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量
  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标
  • front 会随着数据输出而改变,而 rear 则是随着数据输入而改变
  • 当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:
  1. 将尾指针往后移:rear+1 。 当 front == rear 【空】
  2. 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。当rear == maxSize - 1[队列满]

 普通队列代码实现

1. class arrayqueue {  
2.     private int maxSize;//定义队列的最大长度  
3.     private int front;//队列头  
4.     private int rear;//队列尾  
5.     private int[] arr;//用于存储数据  
6.   
7.     public arrayqueue(int maxSize) {  
8.         this.maxSize = maxSize;  
9.         this.arr = new int[maxSize];  
10.         this.front = -1;//指向队列头部,分析出front是指向队列头的第一个数据(最早加进数组的)  
11.         this.rear = -1;//指向队列尾部,分析出rear指向队列最后一个数据(最新加进数组的)  
12.     }  
13.   
14.     /** 
15.      * 判断队列是否为满 
16.      * 
17.      * @return 
18.      */  
19.     public boolean isFull() {  
20.         return rear == maxSize - 1;  
21.     }  
22.   
23.     /** 
24.      * 判断队列是否为空 
25.      * 
26.      * @return 
27.      */  
28.     public boolean isEmpty() {  
29.         return front == rear;  
30.     }  
31.   
32.     /** 
33.      * 数据入队列 
34.      * 
35.      * @param data 
36.      */  
37.     public void addQueue(int data) {  
38.         if (isFull()) {  
39.             throw new RuntimeException("队列已满。");  
40.         }  
41.         rear++;//rear后移  
42.         arr[rear] = data;  
43.     }  
44.   
45.     /** 
46.      * 数据出队列 
47.      * 
48.      * @return arr[front] 
49.      */  
50.     public int getQueue() {  
51.         if (isEmpty()) {  
52.             throw new RuntimeException("队列为空。");  
53.         }  
54.         front++;//front后移  
55.         return arr[front];  
56.     }  
57.   
58.     /** 
59.      * 获取队列第一个元素 
60.      * 
61.      * @return 
62.      */  
63.     public int headQueue() {  
64.         if (isEmpty()) {  
65.             throw new RuntimeException("队列为空。");  
66.         }  
67.         return arr[front + 1];  
68.     }  
69. }  

 

普通队列类的问题及优化

问题分析

1) 目前数组使用一次就不能用, 没有达到复用的效果
2) 解决方案:将这个数组使用算法,改进成一个环形的队列 取模:%

数组模拟环形队列

对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)

  • 分析说明:

1) 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的 时候需要注意 (rear + 1) % maxSize == front [满]
2) rear == front [空]
3)思路分析:

    1. front变量的含义做一个调整:front指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值为0.
    2. rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值为0.
    3. 当队列满时,条件是(rear+1)%MaxSize==front
    4. 当队列为空时,条件为rear==front
    5. 当我们这样分析,队列中有效的数据个数为:(rear+MaxSize-front)%MaxSize
    6. 我们就可以在原来队列的基础上得到一个环形队列

 

 

 环形队列代码实现

1. class criclequeue {  
2.     private int maxSize;//定义队列的最大长度  
3.     //front指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值为0.
4.     private int front;
5.     //rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值为0.
6.     private int rear;
7.     private int[] arr;//用于存储数据  

8.     public criclequeue(int maxSize) {  
9.         this.maxSize = maxSize;  
10.         this.arr = new int[maxSize];  
11.     }  
12.   
13.     /** 
14.      * 判断队列是否为满 
15.      * 
16.      * @return 
17.      */  
18.     public boolean isFull() {  
19.         return (rear + 1) % maxSize == front;  
20.     }  
21.   
22.     /** 
23.      * 判断队列是否为空 
24.      * 
25.      * @return 
26.      */  
27.     public boolean isEmpty() {  
28.         return front == rear;  
29.     }  
30.   
31.     /** 
32.      * 数据入队列 
33.      * 
34.      * @param data 
35.      */  
36.     public void addQueue(int data) {  
37.         if (isFull()) {  
38.             throw new RuntimeException("队列已满。");  
39.         }  
40.         arr[rear] = data;  
41.         rear = (rear + 1) % maxSize;//将rear后移,这里必须考虑取模  
42.     }  
43.   
44.     /** 
45.      * 数据出队列 
46.      * 
47.      * @return arr[front] 
48.      */  
49.     public int getQueue() {  
50.         if (isEmpty()) {  
51.             throw new RuntimeException("队列为空。");  
52.         }  
53.         int data = arr[front];  
54.         front = (front + 1) % maxSize;  
55.         return data;  
56.     }  
57.   
58.     /** 
59.      * 获取队列第一个元素 
60.      * 
61.      * @return 
62.      */  
63.     public int headQueue() {  
64.         if (isEmpty()) {  
65.             throw new RuntimeException("队列为空。");  
66.         }  
67.         return arr[front];  
68.     }  
69.   
70.     /** 
71.      * 遍历队列 
72.      */  
73.     public void showQueue() {  
74.         if (isEmpty()) {  
75.             throw new RuntimeException("队列为空");  
76.         }  
77.         for (int i = front; i < front + this.size(); i++) {  
78.             System.out.print(arr[i % maxSize] + " ");  
79.         }  
80.         System.out.println();  
81.     }  
82.   
83.     /** 
84.      * 获取队列中元素个数 
85.      */  
86.     public int size() {  
87.         return (rear + maxSize - front) % maxSize;  
88.     }  
89. }  

来自 <http://www.planetb.ca/projects/syntaxHighlighter/popup.php> 

 

posted @ 2020-10-15 17:46  白刃天使  阅读(296)  评论(0编辑  收藏  举报