目录
顺序队列
管理结构体设计
初始化
入队
出队
链式队列
例子 用户输入整数则入队,字母则出队
我们对队列里的元素操作是有严格限制的:插入一个新节点,必须插入到 指定的一端,而删除一个已有节点,则必须在另一端进行。当我们对一个线性表严格地执行 这样的限制的话,这种线性表就是一种特殊的线性表,称之为队列。为了方便描述,将队列 的插入称为入队,删除称为出队。可以插入节点的那一端称之为队尾,另一端则称之为队头
队列这种逻辑结构同样可以使用顺序存储或者使用链式存储,使用顺序存储时,由于出 队入队分别在两端进行,为了避免数据的成片移动造成效率损失,可以考虑使用两个分别指 示队头和队尾的偏移量,来辅助队列操作。而对于链式存储来说,也可以使用类似的组织方 式,用队头和队尾指针来分别指向相应的节点
顺序队列
采用一片连续的内存来存放队列元素,使用两个分别代表队头和队尾距离队列基地址的偏移量来控制队 列,另外可以再加上队列当前元素个数等信息
管理结构体设计
typedef int datatype;typedef struct // 队列管理结构体
{datatype *queue; // 队列指针unsigned int size; // 队列空间大小int front; // 队头元素偏移量int rear; // 队尾元素偏移量
}sequent_queue
初始化
typedef int datatype;
sequent_queue *init_queue(unsigned int size) // 初始化一个空队列
{// 申请一块管理结构体内存sequent_queue *q = malloc(sizeof(sequent_queue));if(q != NULL){q->queue = calloc(size, sizeof(datatype)); // 申请队列内存q->size = size;q->front = 0;q->rear = 0;}return q;
}
init_queue( )所得到的空队列
注意:初始化一个空的顺序队列时,我们只需要使得队头和队尾偏移量相等即可,不一 定非要等于 0,后期在判断队列是否为空的时候,判断的依据就是 front 是否等于 rear, 至于他们究竟指示了顺序队列中的哪个地方是无所谓的,因为我们即将看到,我们会循环第 利用这个顺序存储的空间。
入队
现在有一个元素要入队,那么我们就让其排在原队列的队 尾处(不能插队,这才合理),于是我们让 rear 往后增加一个偏移量,让数据 A 入队,紧 接着让数据 B、数据 C 等等依次入队,rear 不断向后偏移
此时虽然顺序队列中还有一个位置是空着的(front 所指示的位置),但是这个 位置目前不能使用,因为如果将数据再填入这个地方,那么 front 和 rear 又再一次相等, 而这两者相等恰恰是判断队列是否为空的标志,事实上此时队列已经满了
bool en_queue(sequent_queue *q, datatype data)
{if(queue_full(q))return false;q->rear = (q->rear+1) % q->size; // 结果要对 size 求余q->queue[q->rear] = data;return true;
}
出队
我们要“循环”地利用顺序队列的空间,因此在 A 和 B 出队之后, F 和 G 理应可以重复利用他们的空间,这就要求在给 rear 增量的同时必须保证 rear 的范 围要落在 size 之内
bool de_queue(sequent_queue *q, datatype *pdata)
{if(queue_empty(q))return false;q->front = (q->front+1) % q->size; // 结果要对 size 求余*pdata = q->queue[q->front];return true;
}
判断队满不满,空不空
bool queue_full(sequent_queue *q) // 判断队列是否已满
{return q->front == (q->rear+1) % q->size;
}bool queue_empty(sequent_queue *q)
{return q->front == q->rear;
}
链式队列
入队操作时需要着重注意的是:第一个入队的元素要 额外处理,因为一开始 front 和 rear 都是 NULL,不能进行任何的接引用。出队操作需要 注意的是:如果出队的元素是队列中的唯一的元素,那么队头和队尾指针都必须置空
例子 用户输入整数则入队,字母则出队
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4
5 typedef int datatype;
6
7 struct node // 队列节点
8 {
9 datatype data;
10 struct node *next;
11 };
12
13 typedef struct // 管理结构体
14 {
15 struct node *front;
16 struct node *rear;
17 unsigned int size;
18 }linked_queue;
19
20 linked_queue *init_queue(void) // 初始化一个空队列
21 {
22 linked_queue *q = malloc(sizeof(linked_queue));
23 if(q != NULL)
24 {
25 q->front = q->rear = NULL;
26 q->size = 0;
27 }
28 return q;
29 }
30
31 struct node *new_node(datatype data) // 创建一个新节点
32 {
33 struct node *new = malloc(sizeof(struct node));
34 if(new != NULL)
35 {
36 new->data = data;
37 new->next = NULL;
38 }
39 return new;
40 }
41
42 bool queue_empty(linked_queue *q) // 判断队列是否为空
43 {
44 return q->size == 0;
45 }
46
47 bool en_queue(linked_queue *q, struct node *new) // 入队
48 {
49 if(new == NULL)
50 return false;
51
52 if(queue_empty(q)) // 如果是第一个节点,要额外处理
53 {
54 q->front = q->rear = new;
55 }
56 else
57 {
58 q->rear->next = new;
59 q->rear = new;
60 }
61
62 q->size++; // size 记录了当前队列的元素个数,入队需加 1
63 return true;
64 }
65
66 bool singular(linked_queue *q) // 判断队列是否刚好只剩一个元素
67 {
68 return (!queue_empty(q)) && (q->front == q->rear);
69 }
70
71 bool de_queue(linked_queue *q, struct node **p) // 出队
72 {
73 if(queue_empty(q)) // 如果队列为空,则立即出错返回
74 return false;
75
76 struct node *tmp = q->front;
77
78 if(singular(q)) // 如果队列只剩一个节点,则出队之后队列被置空
79 {
80 q->front = q->rear = NULL;
81 }
82 else
83 {
84 q->front = q->front->next;
85 }
86
87 if(p != NULL) // p 如果不为 NULL 则使 *p 指向原队头元素
88 {
89 tmp->next = NULL;
90 *p = tmp;
91 }
92 else // p 如果为 NULL 则直接释放原队头元素
93 {
94 free(tmp);
95 }
96 q->size--;
97
98 return true;
99 }
100
101 void show(linked_queue *q) // 显示队列元素
102 {
103 if(queue_empty(q))
104 return;
105
106 struct node *tmp = q->front;
107
108 while(tmp != NULL)
109 {
110 printf("%d\t", tmp->data);
111 tmp = tmp->next;
112 }
113 printf("\n");
114 }
115
116 int main(void)
117 {
118 linked_queue *q;
119 q = init_queue(); // 初始化一个空队列
120
121 int n, ret;
122 while(1)
123 {
124 ret = scanf("%d", &n); // 接收用户输入
125
126 if(ret == 1) // 如果输入的是整数,则将该整数入队
127 {
128 struct node *new = new_node(n);
129 en_queue(q, new);
130 show(q);
131 }
132 else if(ret == 0) // 如果输入非整数,则将队头元素出队
133 {
134 struct node *tmp;
135 de_queue(q, &tmp);
136 show(q);
137 while(getchar() != '\n');
138 }
139 }
140
141 return 0;
142 }