西风的数据结构教程(2)——队列

来源:互联网 发布:UNetbootin ubuntu 编辑:程序博客网 时间:2024/05/07 21:38

队列是一种简单的先进先出结构,各种需要排队的事情,都可以开一个队列来完成。
利用链表或数组,都能实现队列,不过最大的区别就是,数组的扩展比较困难,而链表较为容易,但链表资源消耗稍多。

数据结构的不同导致了队列的实现也不相同,链表上次已经实现过了,只需简单包装即可使用,这里,我们介绍简单的用数组模拟队列的方式:

简单队列

这个队列是固定长度的一个数组构建的,另外保存两个int数字,负责记录数组的下标索引。

我们下面就来编写一下这个队列,还是使用C语言,在此,我会继续介绍C语言的基础知识。

队列实现

复习一下上次的知识,C语言定义基本结构和宏定义,我们也先对队列进行必要的定义

/* queue.h */#ifndef QUEUE_H#define QUEUE_H#include "malloc.h"typedef char bool;typedef int QueueElementType;#define QueueSize 200typedef struct _queue{    int head, tail;    QueueElementType data_array[QueueSize];} queue;#endif // QUEUE_H

注意这里,我们提前设置了队列的长度,对于不知道队列具体应该多长的问题,可能并不大合适,不过过后我们会介绍如何计算队列需要的最大长度。

依旧是定义四个函数:

/* 队列的构造函数 */queue* QueueCreate(); /* 从结尾压入元素 */void QueuePush(queue* q, QueueElementType data);/* 从头部弹出元素 */QueueElementType QueuePop(queue* q);/* 判断队列是否为空 */bool QueueIsEmpty(queue* q);

比较简单的构造函数和判断函数这里直接给出,注意初始化的条件是头尾指针皆为0:

queue* QueueCreate() {    queue* q = (queue*) malloc(sizeof(queue));    q->head = 0;    q->tail = 0;     return q;}bool QueueIsEmpty(queue* q) {    return q->head == q->tail;}

至于压入弹出也很简单,但需要注意的是,为了减少内存消耗,我们希望这个队列是循环队列。
(PS. 当年的唐山一中TSOI,有一句经典搞笑语录,“队列是先进先出的,循环队列是进进出出的。” 哎,跑题了,大家无视无视。)

至于什么是循环队列,大家请看下面这张图:

循环队列

恩,通过模运算就让队列循环运动,很方便的设计,不过还是要注意,永远不要让tail追上head,那时,队列就溢出了。
所以,我们的操作函数Push和Pop是这样的:

void QueuePush(queue* q, QueueElementType data) {    q->data_array[ q->tail ] = data;    q->tail = ++(q->tail) % QueueSize;}QueueElementType QueuePop(queue* q) {    if (QueueIsEmpty(q)) return (QueueElementType)NULL;    QueueElementType data = q->data_array[ q->head ];    q->head = ++(q->head) % QueueSize;    return data;}

队列的使用当然十分简单,只需要操作这四个函数即可:

#include <stdio.h>#include "queue.h"queue* q = NULL;int main() {    q = QueueCreate();    QueuePush(q, 10);    QueuePush(q, 20);    QueuePush(q, 30);    printf("%d\n", QueuePop(q));    printf("%d\n", QueuePop(q));    printf("%d\n", QueuePop(q));    return 0;}

完整的代码详见附录,这里就不再具体多说了。

队列的应用

说了队列的写法,那么应该介绍一下,队列都有哪些用途。广搜问题,是让我最早认识队列的问题,这里就给大家举一个迷路小孩回家问题吧= =,画着X的地方表示无法通行,给他找一条可行的路径。

队列的应用,迷路小孩

开一个队列,记录已经走的步数和当前的位置,然后根据地图结构,每次看队列新弹出的元素的位置,分别向四个方向搜索,如果已经搜索过的就不要找了,整个搜索过程就像漫水一样,这样就能找到可行的路径了。
怎么样,这就是搜索问题中经典的广度优先遍历,是不是也很简单呢?

0 0
原创粉丝点击