前面学习了基于顺序表以及链式表的堆栈操作,这里的链式表指单向链表,这篇文章学习同样是基于顺序表以及链式表的队列操作。 |
队列与堆栈的不同之处在于队列是先进先出,即队列的两边都可以进行操作,一头压入,另一头弹出。这就需要用到头指针和尾指针两个指针,为了避免指针指向空的内存,因此这两个头尾指针可以循环,而且当队列处于空或者满状态的时候,头尾指针均可能重合。
基于顺序表的实现,初始化空间,操作前端和后端两个指针,前端指针负责弹出,后端指针负责压入,并且循环使用存储空间,判断空和满。
在进程等待的时候就是将进程先放入消息队列中,先进来先进行处理,这也是一个队列的实现。
队列的操作其实和前面的堆栈很像,下面就用程序来实现一下队列的操作 |
基于顺序表的队列 |
头文件
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: order.h
* Description: This head file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 09:25:50 AM"
*
********************************************************************************/
#ifndef _ORDER_H
#define _ORDER_H
#include <stdio.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct Queue{
int* arr; /* 数组 */
size_t cap; /* 容量 */
size_t front;/* 前端弹出 */
size_t rear; /* 后端压入 */
size_t size; /* 大小 */
} QUEUE;
/* 分配内存并初始化为空队列 */
void queue_init(QUEUE* queue, size_t cap);
/* 释放内存并恢复到初始状态 */
void queue_deinit(QUEUE* queue);
/* 判断是否满 */
bool queue_full(QUEUE* queue);
/* 判断是否空 */
bool queue_empty(QUEUE* queue);
/* 压入 */
void queue_push(QUEUE* queue, int data);
/* 弹出 */
int queue_pop(QUEUE* queue);
/* 队首 */
int queue_front(QUEUE* queue);
/* 大小 */
size_t queue_size(QUEUE* queue);
#endif /* _ORDER_H */
C文件
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: order.h
* Description: This head file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 09:25:50 AM"
*
********************************************************************************/
#include "order.h"
/* 分配内存并初始化为空队列 */
void queue_init(QUEUE* queue, size_t cap)
{
queue->arr = malloc(cap * sizeof(queue->arr[0])); //为数组分配内存空间大小
queue->cap = cap; //容量
queue->rear = 0;
queue->front = 0;
queue->size = 0;
}
/* 释放内存并恢复到初始状态 */
void queue_deinit(QUEUE* queue)
{
free(queue->arr);
queue->arr = NULL;
queue->cap = 0;
queue->front = 0;
queue->rear = 0;
queue->size = 0;
}
/* 判断是否满 */
bool queue_full(QUEUE* queue)
{
return queue->size >= queue->cap;
}
/* 判断是否空 */
bool queue_empty(QUEUE* queue)
{
return !queue->size;
}
/* 压入 */
void queue_push(QUEUE* queue, int data) //满了不能压
{
if(queue->rear >= queue->cap)
{
queue->rear = 0;
}
++queue->size;
queue->arr[queue->rear++] = data;
}
/* 弹出 */
int queue_pop(QUEUE* queue)
{
if(queue->front >= queue->cap) //空了不能弹
{
queue->front = 0;
}
--queue->size;
return queue->arr[queue->front++];
}
/* 队首 */
int queue_front(QUEUE* queue)
{
if(queue->front >= queue->cap)
{
queue->front = 0;
}
return queue->arr[queue->front];
}
/* 大小 */
size_t queue_size(QUEUE* queue)
{
return queue->size;
}
测试程序:
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: otest.c
* Description: This file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 09:45:15 AM"
*
********************************************************************************/
#include "order.h"
int main(int argc, char **argv)
{
QUEUE queue;
queue_init(&queue, 9);
int i = 0;
for (i = 10; i <= 50; i+=10)
{
if (!queue_full(&queue))
{
queue_push(&queue, i);
}
}
for (i = 0; i < 2; ++i)
{
if (!queue_empty(&queue))
{
printf("%d\n", queue_pop(&queue));
}
}
for (i = 50; i <= 80; i+=10)
{
if (!queue_full(&queue))
{
queue_push(&queue, i);
}
}
while(!queue_empty(&queue))
{
printf("%d\n", queue_pop(&queue));
}
queue_deinit(&queue);
return 0;
}
结果:
[tangyanjun@VM_216_80_centos queue]$ gcc order.c otest.c
[tangyanjun@VM_216_80_centos queue]$ a.out
10
20
30
40
50
50
60
70
80
由此可见队列先进先出的特点
基于链表的队列 |
头文件:
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: lq.h
* Description: This head file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 09:25:50 AM"
*
********************************************************************************/
#ifndef _LQ_H
#define _LQ_H
#include <stdio.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct QueueNode{
int data; //数据
struct QueueNode* next; //后指针
} QUEUE_NODE;
typedef struct Queue{
QUEUE_NODE* front; //弹出,前端
QUEUE_NODE* rear; //压入,后端
} QUEUE;
/* 分配内存并初始化为空队列 */
void queue_init(QUEUE* queue);
/* 释放剩余节点并恢复到初始状态 */
void queue_deinit(QUEUE* queue);
/* 判断是否空 */
bool queue_empty(QUEUE* queue);
/* 压入 */
void queue_push(QUEUE* queue, int data);
/* 弹出 */
int queue_pop(QUEUE* queue);
/* 队首 */
int queue_front(QUEUE* queue);
/* 大小 */
size_t queue_size(QUEUE* queue);
#endif /* _LQ_H */
C文件
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: lq.c
* Description: This head file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 09:25:50 AM"
*
********************************************************************************/
#include "lq.h"
/* 创建节点 */
static QUEUE_NODE* create_node(int data)
{
QUEUE_NODE* node = malloc(sizeof(QUEUE_NODE));
node->data = data;
node->next = NULL;
return node;
}
/* 销毁节点 */
static QUEUE_NODE* destroy_node(QUEUE_NODE* node)
{
QUEUE_NODE* next = node->next;
free(node);
return next;
}
/* 初始化为空队列 */
void queue_init(QUEUE* queue)
{
queue->front = NULL;
queue->rear = NULL;
}
/* 释放剩余节点并恢复到初始状态 */
void queue_deinit(QUEUE* queue)
{
while(queue->front)
{
queue->front = destroy_node(queue->front);
}
queue->rear = NULL;
}
/* 判断是否空 */
bool queue_empty(QUEUE* queue)
{
return !queue->front && !queue->rear;
}
/* 压入 */
void queue_push(QUEUE* queue, int data)
{
QUEUE_NODE* node = create_node(data);
if (queue->rear)
{
queue->rear->next = node;
}
else
{
queue->front = node;
}
queue->rear = node;
}
/* 弹出 */
int queue_pop(QUEUE* queue)
{
int data = queue->front->data;
if (!(queue->front = destroy_node(queue->front)))
{
queue->rear = NULL;
}
return data;
}
/* 队首 */
int queue_front(QUEUE* queue)
{
return queue->front->data;
}
/* 大小 */
size_t queue_size(QUEUE* queue)
{
size_t size = 0;
QUEUE_NODE* node = NULL;
for (node = queue->front; node; node = node->next)
{
++size;
}
return size;
}
测试程序
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: lqtest.c
* Description: This file
*
* Version: 1.0.0(07/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/24/2017 10:46:52 AM"
*
********************************************************************************/
#include <string.h>
#include <stdlib.h>
#include "lq.h"
int main(int argc, char **argv)
{
QUEUE queue;
queue_init (&queue);
char text[20];
for(;;)
{
fgets(text, 20, stdin);
if (strcmp(text, "!") == 0)
{
break;
}
queue_push(&queue, (int)strcpy(malloc((strlen(text) + 1) * sizeof(char)), text));
}
printf("-----------------\n");
while(!queue_empty(&queue))
{
char* ps = (char*)queue_pop(&queue);
printf("%s\n", ps);
free(ps);
}
queue_deinit(&queue);
return 0;
}
当我们输入“!”时,输入结束,屏幕按队列顺序打印出我们的输入。