数据结构3.队列
队列:
有两个端口,一个端口只能入队,另一个端口只能出队,先进先出 FIFO
顺序队列:
数据项:
存储元素的内存首地址
容量
队头下标 //出队
队尾下标 //入队
运算:
创建、销毁、入队、出队、队空、队满、查队头、查队尾、数量
顺序队列的注意点:
由一维数组+队头下标front+队尾下标tail组成,入队tail++,出队front++,为了让队列能够反复使用,我们把队列想象成一个环,
因此当front 和 tail 加1后都需要队列容量求余再重新赋值
front = (front + 1) % cal;
tail = (tail + 1) % cal;
如何判断队空、队满:
额外多申请一个元素的内存
队空:front == tail;
队满:(tail+1)%cal == front
第一种代价是空了一个位置不能使用,计算数量时较为麻烦(最常考)
计算数量:(tail - front +cal)%cal
第二种方式是队列结构中多加了一项数据项用于记录队列中元素个数,判断空或满直接判断该数据项即可,更方便
第一种:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
typedef struct ArrayQueue
{
TYPE* ptr;
size_t cal;
size_t front; // 队头下标
size_t tail; // 队尾下标 指向即将入队的位置
}ArrayQueue;
//创建顺序队列
//多申请一个内存 解决队空队满判断问题
ArrayQueue* create_array_queue(size_t cal)
{
ArrayQueue* queue = malloc(sizeof(ArrayQueue));
queue0>ptr = malloc(sizeof(TYPE)* (cal+1));
queue->cal = cal+1;
queue->front = 0;
queue-> tail = 0;
return queue;
}
//销毁
void destory_array_queue(ArrayQueue* queue)
{
free(queue->ptr);
free(queue);
}
//队空
bool empty_array_queue(ArrayQueue* queue)
{
return queue->front == queue->tail;
}
//队满
bool full_array_queue(ArrayQueue* queue)
{
return queue->(tail+1)%queue->cal == queue->front;
}
//入队
bool push_array_queue(ArrayQueue* queue,TYPE val)
{
if(full_array_queue(queue)) return false;
queue->ptr[queue->tail] = val;
queue->tail = (queue->tail+1)%queue->cal;
return true;
}
//出队
bool pop_arary_queue(ArrayQueue* queue)
{
if(empty_array_queue(queue)) return false;
queue->front = (queue->front+1)%queue->cal;
return true;
}
//队头
TYPE front_array_queue(ArrayQueue* queue)
{
return queue->ptr[queue->front];
}
//队尾
TYPE back_array_queue(ArrayQueue* queue)
{
return queue->ptr[(queue->tail-1+queue->cal)%queue->cal];
}
//数量
size_t size_array_queue(ArrayQueue* queue)
{
return (queue->tail-queue->front+queue->cal)%queue->cal;
}
int main(int argc,const char* argv[])
{
ArrayQueue* queue = create_array_queue(10);
for(int i=0; i<10; i++)
{
push_array_queue(queue,i);
printf("tail:%d size:%d\n",
back_array_queue(queue),size_array_queue(queue));
}
printf("---------\n");
for(int i=0; i<10; i++)
{
printf("front:%d size:%d\n",
front_array_queue(queue),size_array_queue(queue));
pop_array_queue(queue);
}
}
(第二版本)顺序队列:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
typedef struct ArrayQueue
{
TYPE* ptr;
size_t cal; //容量
size_t cnt; //已存储的元素个数
size_t front; // 队头下标
size_t tail; // 队尾下标 -1开始
}ArrayQueue;
//创建顺序队列
ArrayQueue* create_array_queue(size_t cal)
{
ArrayQueue* queue = malloc(sizeof(ArrayQueue));
queue0>ptr = malloc(sizeof(TYPE)* (cal));
queue->cal = cal;
queue->cnt = 0;
queue->front = 0;
queue-> tail = -1; //指向最后一个元素
return queue;
}
//销毁
void destory_array_queue(ArrayQueue* queue)
{
free(queue->ptr);
free(queue);
}
//队空
bool empty_array_queue(ArrayQueue* queue)
{
return 0 == queue->cnt;
}
//队满
bool full_array_queue(ArrayQueue* queue)
{
return queue->cnt == queue->cal;
}
//入队
bool push_array_queue(ArrayQueue* queue,TYPE val)
{
if(full_array_queue(queue)) return false;
queue->tail = (queue->tail+1)%queue -> val;
queue->ptr[queue->tail] = val;
queue->cnt++;
return true;
}
//出队
bool pop_arary_queue(ArrayQueue* queue)
{
if(empty_array_queue(queue)) return false;
queue->front = (queue->front+1)%queue->cal;
queue->cnt--;
return true;
}
//队头
TYPE front_array_queue(ArrayQueue* queue)
{
return queue->ptr[queue->front];
}
//队尾
TYPE back_array_queue(ArrayQueue* queue)
{
return queue->ptr[queue->tail];
}
//数量
size_t size_array_queue(ArrayQueue* queue)
{
return queue->cnt;
}
int main(int argc,const char* argv[])
{
ArrayQueue* queue = create_array_queue(10);
for(int i=0; i<10; i++)
{
push_array_queue(queue,i);
printf("tail:%d size:%d\n",
back_array_queue(queue),size_array_queue(queue));
}
printf("---------\n");
for(int i=0; i<10; i++)
{
printf("front:%d size:%d\n",
front_array_queue(queue),size_array_queue(queue));
pop_array_queue(queue);
}
}
int main(int argc,const char* argv[])
{
ArrayQueue* queue = create_array_queue(10);
for(int i=0; i<10; i++)
{
push_array_queue(queue,i);
printf("tail:%d size:%d\n",
back_array_queue(queue),size_array_queue(queue));
}
printf("---------\n");
for(int i=0; i<10; i++)
{
printf("front:%d size:%d\n",
front_array_queue(queue),size_array_queue(queue));
pop_array_queue(queue);
}
}
链式队列:
由链表结点组成的队列结构
数据项:
队头指针
队尾指针
结点数量
运算:创建、销毁、队空、入队、出队、队头、队尾
队列应用:
1.消息队列
2.树的层序遍历使用队列
3.图的广度优先遍历使用队列
4.封装线程池、数据池
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int
typedef struct Node
{
TYPE data;
struct Node* next;
}Node;
Node* create_node(TYPE data)
{
Node* node = malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
typedef struct ListQueue
{
Node* front; // 队头指针
Node* tail; // 队尾指针
size_t cnt; // 结点数量
}ListQueue;
// 创建
ListQueue* create_list_queue(void)
{
ListQueue* queue = malloc(sizeof(ListQueue));
queue->front = NULL;
queue->tail = NULL;
queue->cnt = 0;
return queue;
}
// 队空
bool empty_list_queue(ListQueue* queue)
{
return 0 == queue->cnt;
}
// 入队
void push_list_queue(ListQueue* queue,TYPE val)
{
Node* node = create_node(val);
if(empty_list_queue(queue))
{
queue->front = node;
queue->tail = node;
}
else
{
queue->tail->next = node;
queue->tail = node;
}
queue->cnt++;
}
// 出队
bool pop_list_queue(ListQueue* queue)
{
if(empty_list_queue(queue)) return false;
Node* temp = queue->front;
queue->front = temp->next;
queue->cnt--;
if(0 == queue->cnt) queue->tail = NULL;
free(temp);
return true;
}
// 队头
TYPE front_list_queue(ListQueue* queue)
{
return queue->front->data;
}
// 队尾
TYPE back_list_queue(ListQueue* queue)
{
return queue->tail->data;
}
// 数量
size_t size_list_queue(ListQueue* queue)
{
return queue->cnt;
}
// 销毁
void destory_list_queue(ListQueue* queue)
{
while(pop_list_queue(queue));
free(queue);
}
int main(int argc,const char* argv[])
{
ListQueue* queue = create_list_queue();
for(int i=0; i<10; i++)
{
push_list_queue(queue,i);
printf("tail:%d size:%d\n",
back_list_queue(queue),size_list_queue(queue));
}
printf("-------------------\n");
while(!empty_list_queue(queue))
{
printf("front:%d size:%d\n",
front_list_queue(queue),size_list_queue(queue));
pop_list_queue(queue);
}
}