【Java数据结构】循环队列的数组实现

先上一个初级队列的数组实现,缺点是数组不能复用,没有可用性

 于是乎,我们要考虑循环一个数组来实现循环队列,即想办法把用过的位置复用

在上面的代码中,重点是两个下标front和rear,分别指向头和尾,要想复用,就得想办法将rear重新指向数组开始的位置

接下来上我的第一个思路

毫无疑问能想到的肯定是取模,我的思路是,让front和rear一直增长,而通过对maxSize进行取模来控制其取模后的值一直在0到maxSize之间变化

第一个思路的代码如下,在代码中进行部分思路讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
 * @author ZhiYi Li
 * @create 2020/8/24 19:05
 * 循环队列的数组实现
 * 思路:
 * 1、front指向第一个元素,初始值为0
 * 2、rear指向队列的最后一个元素的后一个位置,特意空出一个空间,初始值为0
 * 3、当队列满时,(rear+1)%maxSize = front
 * 4、当队列空时,rear=front
 */
public class CycleArrayQueue {
    private int maxSize;
    private int front;//指向第一个元素的位置
    private int rear;//指向最后一个元素的后一个位置
    private int[] ints;
 
    public CycleArrayQueue(int maxSize) {
        this.maxSize = maxSize+1;//预留一个空位置
        ints = new int[this.maxSize];
        front = 0;
        rear = 0;
    }
 
    private boolean isFull(){
        return (rear + 1) % maxSize == front;
    }
 
    private boolean isEmpty(){
        return front == rear;
    }
 
    public void addItem(int item){
        if(isFull()){
            System.out.println("队列满!");
            return;
        }
        ints[rear%maxSize] = item;
        rear++;
    }
 
    public int getItem(){
        if (isEmpty()){
            System.out.println("队列空!");
        }
        int result = ints[front%maxSize];
        front++;
        return result;
    }
    public void show(){
        if(isEmpty()){
            System.out.println("队列空!");
            return;
        }
        for (int i = front; i < rear; i++) {
            System.out.println(ints[i%maxSize]+" ");
        }
    }
    public void showFront(){
        if (isEmpty()){
            System.out.println("队列空!");
        }
        System.out.println("头数据为:"+ints[front%maxSize]);
    }
 
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }
 
 
}
//以下是测试
class Main2{
    public static void main(String[] args) {
        CycleArrayQueue queue = new CycleArrayQueue(5);
        queue.addItem(2);
        queue.addItem(3);
        queue.addItem(4);
        queue.addItem(5);
        queue.addItem(6);
        System.out.println("队列初始值:");
        queue.show();
        System.out.println("出队列");
        System.out.println(queue.getItem());
        System.out.println("一次出队列后的结果");
        queue.show();
        queue.addItem(7);
        System.out.println("一次进队列的结果:");
        queue.show();
        System.out.println("五次出队后:");
        for (int i = 0; i < 5; i++) {
            queue.getItem();
        }
        queue.show();
        queue.addItem(567);
        System.out.println("一次进队:");
        queue.show();
        queue.showFront();
    }
}

 这种思路是可以通过简单的测试的,但是这种思路会有一个大问题,front和rear都是int型,而int型是有范围上限的(-2147483648到2147483648),所以不能让它一直增长,在数据量大时容易出错

改良的思路是我们可以用取模将front和rear的值保持在范围内

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
 * @author ZhiYi Li
 * @create 2020/8/24 19:05
 * 循环队列的数组实现
 * 思路:
 * 1、front指向第一个元素,初始值为0
 * 2、rear指向队列的最后一个元素的后一个位置,特意空出一个空间,初始值为0
 * 3、当队列满时,(rear+1)%maxSize = front
 * 4、当队列空时,rear=front
 */
public class CycleArrayQueue {
    private int maxSize;
    private int front;//指向第一个元素的位置
    private int rear;//指向最后一个元素的后一个位置
    private int[] ints;
 
    public CycleArrayQueue(int maxSize) {
        this.maxSize = maxSize+1;//预留一个空位置
        ints = new int[this.maxSize];
        front = 0;
        rear = 0;
    }
 
    private boolean isFull(){
        return (rear + 1) % maxSize == front;
    }
 
    private boolean isEmpty(){
        return front == rear;
    }
 
    public void addItem(int item){
        if(isFull()){
            System.out.println("队列满!");
            return;
        }
        ints[rear] = item;
        rear=(rear + 1)%maxSize;
    }
 
    public int getItem(){
        if (isEmpty()){
            System.out.println("队列空!");
        }
        int result = ints[front];
        front = (front+1)%maxSize;
        return result;
    }
    public void show(){
        if(isEmpty()){
            System.out.println("队列空!");
            return;
        }
        //注意遍历时rear会小于front,不能简单的循环遍历
        for (int i = front; i < front +size(); i++) {
            System.out.println(ints[i%maxSize]+" ");
        }
    }
    public void showFront(){
        if (isEmpty()){
            System.out.println("队列空!");
        }
        System.out.println("头数据为:"+ints[front%maxSize]);
    }
 
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }
 
 
}
//以下是测试
class Main2{
    public static void main(String[] args) {
        CycleArrayQueue queue = new CycleArrayQueue(5);
        queue.addItem(2);
        queue.addItem(3);
        queue.addItem(4);
        queue.addItem(5);
        queue.addItem(6);
        System.out.println("队列初始值:");
        queue.show();
        System.out.println("出队列");
        System.out.println(queue.getItem());
        System.out.println("一次出队列后的结果");
        queue.show();
        queue.addItem(7);
        System.out.println("一次进队列的结果:");
        queue.show();
        System.out.println("五次出队后:");
        for (int i = 0; i < 5; i++) {
            queue.getItem();
        }
        queue.show();
        queue.addItem(567);
        System.out.println("一次进队:");
        queue.show();
        queue.showFront();
    }
}

 需要注意的点是在show方法时,我们在第一种代码的show方法的思路上可以发现,第一种show方法的rear实际上就是front+size

完。

 

posted @   枫叶藏在眼眸  阅读(147)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示