队列的基本概念
队列 (Queue) :也是运算受限的线性表。是一种先进先出 (First In First Out ,简称 FIFO) 的线性表。只允许在表的一端进行插入,而在另一端进行删除。
队首 (front) :允许进行删除的一端称为队首。
队尾 (rear) :允许进行插入的一端称为队尾。
队列中没有元素时称为空队列。在空队列中依次加入元素 a 1 , a 2 , …, a n 之后, a 1 是队首元素, a n 是队尾元素。显然退出队列的次序也只能是 a 1 , a 2 , …, a n ,即队列的修改是依先进先出的原则进行的,如图 3-5 所示。
基本操作
1、创建新队列
2、判空
3、进队
4、出队
5、清空队
6、获得队头元素
7、遍历队
8、销毁队
9、队长
顺序队列
利用一组连续的存储单元 ( 一维数组 ) 依次存放从队首到队尾的各个元素,称为顺序队列。对于队列,和顺序栈相类似,也有动态和静态之分。这里介绍静态顺序队列.其类型定义如
下:
typedef int datatype;
#define MAX_QUEUE_SIZE 100
typedef struct queue
{
datatype queue_array[MAX_QUEUE_SIZE];
int front;
int rear;
}sp_queue;
设立一个队首指针 front ,一个队尾指针rear ,分别指向队首和队尾元素。
◆ 初始化: front=rear =0。
◆ 入队:将新元素插入 rear 所指的位置,然后rear 加 1 。
◆ 出队:删去 front 所指的元素,然后加 1 并返回被删元素。
◆ 队列为空: front=rear 。
◆ 队满: rear = MAX_QUEUE_SIZE - 1 或front=rear 。
在非空队列里,队首指针始终指向队头元素,而队尾指针始终指向队尾元素的下一位置。顺序队列中存在“假溢出”现象。因为在入队和出队操作中,头、尾指针只增加不减小,致使被删除元素的空间永远无法重新利用。因此,尽管队列中实际元素个数可能远远小于数组大小,但可能由于尾指针巳超出向量空间的上界而不能做入队操作。该现象称为假溢出。如图 3-6 所示是数组大小为 5 的顺序队列中队首、队尾指针和队列中元素的变化情况。
代码实现:
1 /* 顺序队列接口定义头文件*/ 2 #define true 1 3 #define false 0 4 5 6 /* 队的最大长度 */ 7 #define MAX_QUEUE_SIZE 100 8 /* 队列的数据类型 */ 9 typedef int datatype; 10 11 /* 静态链的数据结构 */ 12 typedef struct queue{ 13 datatype sp_queue_array[MAX_QUEUE_SIZE]; 14 /* 队头 */ 15 int front; 16 /* 队尾 */ 17 int rear; 18 }sp_queue; 19 20 21 /* 静态顺序链的接口定义 */ 22 23 24 /* 静态链的初始化 */ 25 sp_queue queue_init(); 26 27 /* 判断队列是否为空,若为空 28 * 返回true 29 * 否则返回false 30 */ 31 int queue_empty(sp_queue q); 32 33 34 /* 插入元素e为队q的队尾新元素 35 * 插入成功返回true 36 * 队满返回false 37 */ 38 int queue_en(sp_queue *q, datatype e); 39 40 41 /* 队头元素出队 42 * 用e返回出队元素,并返回true 43 * 若队空返回false 44 */ 45 int queue_de(sp_queue *q, datatype *e); 46 47 /* 清空队 */ 48 void queue_clear(sp_queue *q); 49 50 51 /* 获得队头元素 52 * 队列非空,用e返回队头元素,并返回true 53 * 否则返回false 54 */ 55 int get_front(sp_queue, datatype *e ); 56 57 58 /* 获得队长 */ 59 int queue_len(sp_queue q); 60 61 /* 遍历队 */ 62 void queue_traverse(sp_queue q, void(*visit)(sp_queue q)); 63 64 65 void visit(sp_queue s); 66 67 68 /* 接口实现文件 */ 69 #include<stdio.h> 70 #include<stdlib.h> 71 #include"sp_queue.h" 72 73 74 sp_queue queue_init() 75 { 76 sp_queue q; 77 q.front = q.rear = 0; 78 return q; 79 } 80 81 82 83 int queue_empty(sp_queue q) 84 { 85 return q.front == q.rear; 86 } 87 88 89 int queue_en(sp_queue *q, datatype e) 90 { 91 /* 队满 */ 92 if (q -> rear == MAX_QUEUE_SIZE) 93 return false; 94 95 /* 入队 */ 96 q -> sp_queue_array[q -> rear] = e; 97 printf("q.sp_queue_array[%d]=%d ", q -> rear, e); 98 q -> rear += 1; 99 return true; 100 101 } 102 103 104 int queue_de(sp_queue *q, datatype *e) 105 { 106 /* 队空 */ 107 if(queue_empty(*q)) 108 return false; 109 110 /* 出队 */ 111 q -> rear -= 1; 112 *e = q -> sp_queue_array[q -> rear]; 113 return true; 114 } 115 116 117 void queue_clear(sp_queue *q) 118 { 119 q -> front = q -> rear = 0; 120 } 121 122 123 int get_front(sp_queue q, datatype *e) 124 { 125 /* 队空 */ 126 if(q.front == q.rear) 127 return false; 128 129 /* 获取队头元素 */ 130 *e = q.sp_queue_array[q.front]; 131 return true; 132 } 133 134 135 int queue_len(sp_queue q) 136 { 137 return (q.rear - q.front); 138 } 139 140 141 void queue_traverse(sp_queue q, void (*visit)(sp_queue q)) 142 { 143 visit(q); 144 } 145 146 void visit(sp_queue q) 147 { 148 /* 队空 */ 149 if (q.front == q.rear) 150 printf("队列为空 "); 151 152 int temp = q.front; 153 while(temp != q.rear) 154 { 155 printf("%d ",q.sp_queue_array[temp]); 156 temp += 1; 157 } 158 printf(" "); 159 } 160 161 162 163 int main() 164 { 165 sp_queue q = queue_init(); 166 queue_en(&q, 1); 167 queue_en(&q, 2); 168 printf("length=%d ", queue_len(q)); 169 queue_en(&q, 3); 170 printf("length=%d ", queue_len(q)); 171 queue_en(&q, 4); 172 printf("length=%d ", queue_len(q)); 173 queue_en(&q, 5); 174 printf("length=%d ", queue_len(q)); 175 queue_en(&q, 6); 176 printf("length=%d ", queue_len(q)); 177 queue_traverse(q,visit); 178 datatype *e = (datatype *)malloc(sizeof(*e)); 179 queue_de(&q,e); 180 printf("queue_de(),e=%d length=%d ", *e, queue_len(q)); 181 queue_traverse(q, visit); 182 queue_clear(&q); 183 queue_traverse(q, visit); 184 printf("length:%d ", queue_len(q)); 185 }
队列的链式表示和实现
队列的链式存储结构简称为链队列,它是限制仅在表头进行删除操作和表尾进行插入操作的单链表。需要两类不同的结点:数据元素结点,队列的队
首指针和队尾指针的结点,如图 3-8 所示。
数据元素结点类型定义:
typedef struct q_node{
datatype data;
struct q_node *next;
}q_node;
指针结点类型:
typedef struct {
q_node *front;
q_node *rear;
}link_queue;
链队运算及指针变化
链队的操作实际上是单链表的操作,只不过是删除
在表头进行,插入在表尾进行。插入、删除时分别修改
不同的指针。链队运算及指针变化如图 3-9 所示。
代码实现:
1 /* 链式栈接口的定义头文件 */ 2 #define true 1 3 #define false 0 4 5 6 /* 队列的数据类型 */ 7 typedef int datatype; 8 9 /* 静态链的数据结构 */ 10 typedef struct q_node{ 11 datatype data; 12 struct q_node *next; 13 }q_node,*link_node; 14 15 typedef struct l_queue{ 16 /* 队头指针 */ 17 q_node *front; 18 /* 队尾指针 */ 19 q_node *rear; 20 }*link_queue; 21 22 23 /* 静态顺序链的接口定义 */ 24 25 26 /* 静态链的初始化 */ 27 link_queue queue_init(); 28 29 /* 判断队列是否为空,若为空 30 * 返回true 31 * 否则返回false 32 */ 33 int queue_empty(link_queue q); 34 35 /* 插入元素e为队q的队尾新元素 36 * 插入成功返回true 37 * 队满返回false 38 */ 39 int queue_en(link_queue q, datatype e); 40 41 42 /* 队头元素出队 43 * 用e返回出队元素,并返回true 44 * 若队空返回false 45 */ 46 int queue_de(link_queue q, datatype *e); 47 48 /* 清空队 */ 49 void queue_clear(link_queue q); 50 51 /* 销毁队 */ 52 void queue_destroy(link_queue q); 53 54 /* 获得队头元素 55 * 队列非空,用e返回队头元素,并返回true 56 * 否则返回false 57 */ 58 int get_front(link_queue q, datatype *e ); 59 60 61 /* 获得队长 */ 62 int queue_len(link_queue q); 63 64 /* 遍历队 */ 65 void queue_traverse(link_queue q, void(*visit)(link_queue q)); 66 67 68 void visit(link_queue q); 69 70 71 72 /* 接口的实现文件 */ 73 #include<stdio.h> 74 #include<stdlib.h> 75 #include"lp_queue.h" 76 77 78 79 link_queue queue_init() 80 { 81 /* 新建头结点 */ 82 link_node new_node = (link_node)malloc(sizeof(q_node)); 83 new_node -> next = NULL; 84 /* 指针结点 */ 85 link_queue q = (link_queue)malloc(sizeof(*q)); 86 q -> front = q -> rear = new_node; 87 return q; 88 } 89 90 91 int queue_empty(link_queue q) 92 { 93 return q -> front == q -> rear; 94 } 95 96 97 int queue_en(link_queue q, datatype e) 98 { 99 /* 新建数据结点 */ 100 link_node new_node = (link_node)malloc(sizeof(q_node)); 101 /* 内存分配失败 */ 102 if(!new_node) 103 return false; 104 new_node -> data = e; 105 q -> rear -> next = new_node; 106 q -> rear = new_node; 107 return true; 108 } 109 110 int queue_de(link_queue q, datatype *e) 111 { 112 /* 队列为空 */ 113 if (q -> front == q -> rear) 114 return false; 115 116 *e = q -> front -> next -> data; 117 link_node temp = q -> front -> next; 118 q -> front -> next = temp -> next; 119 /* 防止丢失尾指针 */ 120 if (temp == q.rear -> next) 121 q -> rear = q -> front; 122 free(temp); 123 temp = NULL; 124 return true; 125 } 126 127 void queue_clear(link_queue q) 128 { 129 /* 头结点 */ 130 link_node head = q -> front -> next; 131 head -> next = NULL; 132 q -> front = q -> rear = head; 133 /* 第一个结点 */ 134 link_node temp = head -> next; 135 while(temp) 136 { 137 link_node p = temp; 138 temp = p -> next; 139 free(p); 140 p = NULL; 141 } 142 } 143 144 145 void queue_destroy(link_queue q) 146 { 147 queue_clear(q); 148 free(q); 149 q = NULL; 150 } 151 152 153 int get_front(link_queue q, datatype *e) 154 { 155 /* 队为空 */ 156 if (q -> front == q -> rear) 157 return false; 158 159 *e = q -> front -> next -> data; 160 link_node temp = q -> front -> next; 161 q -> front -> next = temp -> next; 162 free(temp); 163 temp = NULL; 164 return true; 165 } 166 167 168 int queue_len(link_queue q) 169 { 170 /* 头结点 */ 171 link_node p = q -> front -> next; 172 /* 计数器 */ 173 int count = 0; 174 while(p) 175 { 176 count += 1; 177 p = p -> next; 178 } 179 return count; 180 } 181 182 183 void queue_traverse(link_queue q, void(*visit)(link_queue q)) 184 { 185 visit(q); 186 } 187 188 void visit(link_queue q) 189 { 190 /* 头结点 */ 191 link_node p = q -> front -> next; 192 if(!p) 193 { 194 printf("队列为空"); 195 } 196 while(p) 197 { 198 printf("%d ", p -> data); 199 p = p -> next; 200 } 201 printf(" "); 202 } 203 204 int main() 205 { 206 link_queue q = queue_init(); 207 queue_en(q, 1); 208 queue_en(q, 2); 209 printf("length=%d ", queue_len(q)); 210 queue_en(q, 3); 211 printf("length=%d ", queue_len(q)); 212 queue_en(q, 4); 213 printf("length=%d ", queue_len(q)); 214 queue_en(q, 5); 215 printf("length=%d ", queue_len(q)); 216 queue_en(q, 6); 217 printf("length=%d ", queue_len(q)); 218 queue_traverse(q,visit); 219 datatype *e = (datatype *)malloc(sizeof(*e)); 220 queue_de(q,e); 221 printf("queue_de(),e=%d length=%d ", *e, queue_len(q)); 222 queue_traverse(q, visit); 223 queue_clear(q); 224 queue_traverse(q, visit); 225 printf("length:%d ", queue_len(q)); 226 }