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

队列是一种简单的先进先出结构,各种需要排队的事情,都可以开一个队列来完成。

利用链表或数组,都能实现队列,不过最大的区别就是,数组的扩展比较困难,而链表较为容易,但链表资源消耗稍多。

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

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

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

队列实现

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

/* queue.h */
#ifndef QUEUE_H
#define QUEUE_H

#include "malloc.h"

typedef char bool;
typedef int QueueElementType;
#define QueueSize 200

typedef 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的地方表示无法通行,给他找一条可行的路径。

开一个队列,记录已经走的步数和当前的位置,然后根据地图结构,每次看队列新弹出的元素的位置,分别向四个方向搜索,如果已经搜索过的就不要找了,整个搜索过程就像漫水一样,这样就能找到可行的路径了。

怎么样,这就是搜索问题中经典的广度优先遍历,是不是也很简单呢?

时间: 2024-10-14 01:46:57

西风的数据结构教程(2)——队列的相关文章

西风的数据结构教程(1)——链表

今天,同学熊问了我一些基本数据结构的问题,我想这些基础的东西还是应该好好理解的.其实数据结构应该是计算机技术的基石,各种算法都是在数据管理的基础上运行的. 于是,我打算利用业余时间,将我学过的这部分内容整理出来,并且加上一些自己的创新性的内容,做成一份简明扼要的数据结构教程,然后尽可能的深入探讨一些关于这些内容的创新方法和优雅的实现. 回想当年,高中时期的计算机竞赛生涯,一遍遍的啃那些不懂的知识点,也正是因为如此,我虽不算出色,但也拥有了扎实的基本功,在此,我也要感谢我的恩师,我们唐山一中的郭莲

数据结构6_顺序队列(循环队列)

本文实现了顺序队列,与链队列不同的是,顺序队列需要考虑一个问题, 问题情况如下, 解决办法:循环队列,当rear到分配的数组空间末尾时,转到数组头 但是当q.rear==q.front时,又如何区分一种是空队列,一种是满队列的情况呢 这里有两种方案 本次代码实现了第一种方法,同时设置了一个技术变量length,稍加改动便可实现第二个方法 代码如下: #include<iostream>using namespace std;//该顺序队列为循环队列,解决队尾指针达到最大值,队列中有空闲单元,但

C数据结构-栈和队列,括号匹配举例

1.栈和队列是两种特殊的线性表 运算操作被限定只能在表的一端或两端插入,删除元素,故也称它们为限定的线性表结构 2.栈的基本运算 1).Stackinit(&s) 构造一个空栈 2).Stackempty(s) 判断s是否为空栈,当s为空栈时,函数返回值1 否则 0 3).Push(&s,x)  在栈s 的顶部插入元素x,简称将x入 栈 4).Pop(&s,&x) 在栈s 中删除顶元并将其值保存在x单元中返回,简称将x出栈 5)Gettop(s,&x)  读s栈中的

JavaScript数据结构和算法----队列

前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. 一.创建队列 1.创建一种数据结构来保存队列里面的数据,这里选择数组 2.声明一些栈的方法 enqueue(element(s)) : 添加一个或一些元素到队列的末尾 dequeue() : 移除队列第一个的元素(就是排队在最前面的),同时返回被移除的元素. front() : 返回队列第一个的元

算法系列(六)数据结构之表队列和栈

在http://blog.csdn.net/robertcpp/article/details/51559333一文中,我们讲了排序,这一章来介绍一下基本数据结构:表.队列.栈和它们的简单实现 一.表ADT 1.数组实现顺序表 通过对数组操作,来直接对表进行增删查改操作,这种线性表查找某个位置的元素花费的时间为O(1),但是插入删除元素花费的时间为O(n),如果对表的操作更多的是访问操作,那么选择这种实现更为合适. 下面是一个简单实现 package com.algorithm.list; im

《数据结构教程》(李春葆 主编)课后习题【练习题6】

[6.5] 1 #include <iostream> 2 3 using namespace std; 4 #define MAXN 100 5 #define N 4 6 #define M 4 7 int x,y,num; 8 int a[MAXN][MAXN] = { 9 {0,2,3,4}, 10 {1,5,6,7}, 11 {8,9,10,11}, 12 {12,13,14,15}}; 13 bool FindX(int X) 14 { 15 while(a[x][y]!=X){

数据结构实验之队列一:排队买饭

数据结构实验之队列一:排队买饭 题目描写叙述 中午买饭的人特多,食堂真是太拥挤了,买个饭费劲,理工大的小孩还是非常聪明的,直接奔政通超市,哈哈,确实,政通超市里面也卖饭,有好几种菜,做的比食堂好吃多了,价格也不比食堂贵,而且买菜就送豆浆,吸引了不少童鞋.所以有时吧,人还是非常多的,排队是免不了的,悲剧的是超市仅仅有两个收银窗体. 问题是这种:開始有两队人在排队,如今咱们仅仅研究第一队.如今我们给每一个人一个编号,保证编号各不同样,排在前面的人买完饭就走了,有些人挑完饭就排在后面等待付款.还有一些

浅谈算法和数据结构: 五 优先级队列与堆排序

转载自:http://www.cnblogs.com/yangecnu/p/Introduce-Priority-Queue-And-Heap-Sort.html 浅谈算法和数据结构: 五 优先级队列与堆排序 在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话. 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是

数据结构5_链队列

本文用指针形式实现了先进先出的队列,与栈队列类似,需要设计一个队列节点类,一个队列类, 同时队列类为节点类的友元函数:不过与链栈不同的是,链栈仅用单一指针来实现入栈和出栈 而链队列需要有front和rear两个指针(皆为队列节点类指针),front指针负责处理出列,rear处理入列 #include<iostream>using namespace std;class LinkQueue;class QNode   //每个节点的类{    char *data;    //每个节点的数据类型