1 /*队列,在两端进行操作,入队enQueue,出队deQueue,查看队首元素front
2 有顺序队列和链式队列,顺序队列通常使用循环队列,为什么?
3 因为用数组实现队列的时候,当一个元素进行出队操作,该位置将不再能使用,会造成空间的浪费。
4
5 那么如何初始化循环队列,画图画一个圆形来分析。
6 1.当front和rear都是0开始的时候,入队:rear ++,因为front指向队首,所以rear往后面指,指向队尾元素的后一个位置
7 当队列满的时候,front和rear又同时指向了0号元素,例如6个元素的队列,当5号位置进入的时候,rear+1
8 (注意这里的是循环+1找下一个位置,而不是数值上的+1,要通过取余实现),此时,我们无法通过rear和front区分队列的空和满的状态
9 那么我们就有两个办法:第一:把5号位置空着,不能放东西,即rear如果再往下一个位置的时候就是0的时候为满
10 第二:有时候我们队列中存放的每个东西占用空间很大,空着一个的话会有一点浪费,
11 此时,我们可以给队列增加一个计数器size,去计算是否满了。
12 2.front = 0, rear = 0的前一个元素(循环里的前一个),入队的时候操作照旧rear+1(循环的+1,比如6个元素,5号位置+1 = 0号位置)
13 这就相当于我们栈中的top = 0和top = -1了,当top = 0的时候,top指向的是栈顶元素的前一个空格位置,当top = -1的时候,top指向的就是栈顶元素
14
15
16 链式队列
17 因为我们可能并不知道有多少元素,链式队列可以不断去入队,比较方便
18 由于多了指针域,所以相比较同等长度的顺序队列的话空间耗得更多一点
19 由于单链表的操作基本都是从头到尾去进行的,而队列要操作队头和队尾,所以呢,我们要对链表进行改造
20 用一个front指向表头,用一个rear指向表尾,[front|rear]
21 A -> B -> C -> d
22 \ /
23 front | rear
24 这样的话,删除表头很容易,在表尾入队一个元素也不难
25 如果反过来,a作为表尾,d作为表头,要删除表尾会变得很麻烦,要先找到B,然后修改B的指针域
26 */
27
28 #include<iostream>
29 #include<cstdlib>
30
31 struct Queue
32 {
33 int *data;//为了创建时候动态分配大小
34 int capacity;//容量
35 int front;
36 int rear;
37 //int size; 该程序中使用front和rear的相对位置判断是否队满 所以不需要size了
38 };
39
40 void init(struct Queue *pq, int capacity){
41 pq->capacity = capacity;
42 //因为要用rear即将赶上front的时候判断为满,那么我们又要存放capacity个元素,所以要+1个空间给rear去指着
43 pq-data = (int*)malloc(sizeof(int) * (capacity + 1));
44 pq->front = pq->rear = 0;//也可以用一前一后的方式来初始化front rear,要注意初始化的不一样会导致后面的判断方式不一样
45 }
46
47 int isFull(const struct Queue *pq){//并不需要改变队列,只是查看,所以用了const的指针
48 //比如0...5 当5是rear,再循环+1的时候就是0了,那么如何变成0,5 + 1 % 6 = 0
49 if((pq->rear + 1) % (pq->capacity + 1)== pq->front) return 1;
50 else return 0;
51
52 }
53
54 bool enQueue(struct Queue *pq, int data){
55 //满队异常判断
56 if(isFull(pq)) return 0;
57 else{
58 pq->data[pq->rear] = x;
59 //这里的加1是循环加1 解释参照isFull里面
60 pq->rear = (pq->rear + 1) % (pq->capacity + 1);
61 return 1;
62 }
63 }
64
65 int isEmpty(const struct Queue *pq){
66 return pq->front == pq->rear;
67 }
68
69 int deQueue(struct Queue *pq, int *px){
70 if(isEmpty(pq)) return 0;
71 else{
72 *px = pq->data[pq->front];//出队首
73 pq->front = (pq->front + 1) % (pq->capacity + 1);//出队之后下一个元素为队首 所以要循环+1
74 return 1;
75 }
76 }
77
78 int main(){
79 struct Queue q;
80 init(&q, 5);//队列;容量
81 enQueue(&q, 11);//哪个队列?;入队元素
82 enQueue(&q, 22);
83 enQueue(&q, 33);
84 enQueue(&q, 44);
85 enQueue(&q, 55);
86 enQueue(&q, 66);
87 int x;
88 deQueue(&q, &x);//哪个队列?;出队元素
89 printf("%d\n",x);
90 deQueue(&q, &x);//哪个队列?;出队元素
91 printf("%d\n",x);
92 deQueue(&q, &x);//哪个队列?;出队元素
93 printf("%d\n",x);
94 deQueue(&q, &x);//哪个队列?;出队元素
95 printf("%d\n",x);
96 deQueue(&q, &x);//哪个队列?;出队元素
97 printf("%d\n",x);
98 deQueue(&q, &x);//哪个队列?;出队元素
99 printf("%d\n",x);
100 return 0;
101 }