目录

一、队列的定义

1.1 相关概念和特点

(1)基本概念

(2)队列特点

(3)案例引入

2.1 队列分类

二、队列的表示和实现

2.1 顺序队列的表示和实现

(1)结构体定义

(2)初始化操作

(3)入队操作

(4)出队操作

(5)队列大小与判断队列是否为空

2.2 链式队列的表示和实现

(1)结构体定义

(2)初始化操作

(3)入队操作

(4)出队操作

(5)输出队列全部字符与判断队列是否为空

2.3 双向队列的表示和实现

2.4 循环队列的表示和实现

(1)结构体定义

(2)初始化操作

(3)入队操作

(4)出队操作

(5)全部源码

三、经典实例

3.1 层次遍历

3.2 队列在计算机系统中的应用

3.3 其他实例

四、小结:栈与队列


一、队列的定义

1.1 相关概念和特点

(1)基本概念

队列(queue)是一种先进先出(First In First Out, FIFO )的线性表。它只允许在表的一端进行插入,而在另一端删除元素

这和日常生活中的排队是一致的,最早进入队列的元素最早 离开。在队列中,允许插入的一端称为队尾(rear),允许删除的一端则称为队头(front)

(2)队列特点

先入先出(FIFO)

(3)案例引入

队列在程序设计中也经常出现。一个最典型的例子就是操作系统中的作业排队。在允许多道程序运行的计算机系统中,同时有几个作业运行。如果运行的结果都需要通过通道输出,那就要按请求输入的先后次序排队。每当通道传输完毕可以接受新的输出任务时,队头的作业先从队列中退出做输出操作。凡是申请输出的作业都从队尾进入队列。

图1.1-1 队列示意图

2.1 队列分类

图1.2-1 不同队列结构示意图

二、队列的表示和实现

2.1 顺序队列的表示和实现

(1)结构体定义

    #define MAX 1000typedef struct Queue//队列构造{void *p[MAX];//数据域,数组存储指针(地址)int size;//队列大小} Queue;

(2)初始化操作

图2.1-1 顺序队列初始化

Queue *initQueue()//队列初始化
{Queue *queue = (Queue *)malloc(sizeof(Queue));//在堆区申请内存if (queue == NULL)return NULL; //内存分配失败memset(queue->p, 0, sizeof(void *) * MAX);//为数组p初始化queue->size = 0;return queue;
}

(3)入队操作

int push(void *data, Queue *queue) //入队列,本质是尾插
{if (data == NULL || queue == NULL)return 0;                 //空指针判断,入队列失败queue->p[queue->size] = data; //把data插入在队列末位queue->size++;                //队列大小+1return 1;
}

(4)出队操作

void *pop(Queue *queue) //出队列,即pop出首个元素
{if (queue == NULL || queue->size == 0)return NULL;void *data = queue->p[0]; //需要出队列的元素for (int i = 0; i < queue->size - 1; i++)queue->p[i] = queue->p[i + 1]; //更新队列,剩余的数据地址前移一位free(queue->p[queue->size-1]);queue->p[queue->size-1] = NULL;//将原队列末位数据置空queue->size--;                     //队列大小减1return data;}

(5)队列大小与判断队列是否为空

int isEmptyQueue(Queue *queue)//判断队列是否为空
{if (queue == NULL)return -1;return queue->size == 0; //空时返回1
}
int sizeOfQueue(Queue *queue)//返回队列的大小
{if (queue == NULL)return -1;return queue->size;
}

2.2 链式队列的表示和实现

(1)结构体定义

图2.2-1 链式队列结构

//定义队列
typedef struct qNode{int data;//整型数据(可以根据需要修改数据类型) struct qNode *next;
}qNode,*queue;
typedef struct{queue front;queue rear;
}Queue;

(2)初始化操作

图 2.2-2 链式队列初始化

//初始化队列
void initQueue(Queue &Q){Q.front=Q.rear=(queue)malloc(sizeof(qNode));//队头指针、队尾指针指向同一空结点 Q.front->next=NULL;
}

(3)入队操作

图2.2-3 入队操作

//入队列
void inQueue(Queue &Q,int data){queue p;    p=(queue)malloc(sizeof(qNode));//分配一个结点空间p->data=data;p->next=NULL;Q.rear->next=p;//队尾指针指向pQ.rear=p;//队尾指针后移一位printf("数据 %d 已经入队列\n\n",data);
}

(4)出队操作

图2.2-4 出队操作

//出队列
void outQueue(Queue &Q,int &data){queue p;p=(queue)malloc(sizeof(qNode));//分配一个结点空间p=Q.front->next;//指定一个新的结点指向队头指针指向的结点data=p->data;//返回结点数据值Q.front->next=p->next;//将p指向的下一数据给队头指针,令下一数据前移到队头 printf("数据 %d 已经出队列\n\n",data);if(Q.rear==p){Q.rear=Q.front;//使队尾指针回到初始位置printf("请注意:队列中已经没有数据!\n\n");//提示用户队列无数据 }delete(p);//释放p所指结点空间 }

(5)输出队列全部字符与判断队列是否为空

//判断队列是否为空
bool emptyQueue(Queue &Q){if(Q.front==Q.rear){return false;}else{return true;}
}//输出链队列中储存的全部字符
void outQ(Queue Q){queue q;//辅助变量q=Q.front->next;//如果链队列不为空,输出其全部字符 while(q){printf("%d ",q->data);q=q->next;}printf("\n");//换行
}

2.3 双向队列的表示和实现

这里可以采用双向链表实现,本人并没有实现。因此就暂时不放源码了

如果后续有补充会回来更新。

2.4 循环队列的表示和实现

(1)结构体定义

图2.4-1 循环队列结构

代码实现如下:

// 队列的顺序存储结构(循环队列)
#define MAX_QSIZE 5 // 最大队列长度+1
typedef struct {int *base; // 初始化的动态分配存储空间int front; // 头指针,若队列不空,指向队列头元素int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;

(2)初始化操作

// 构造一个空队列Q
SqQueue* Q_Init() {SqQueue *Q = (SqQueue*)malloc(sizeof(SqQueue));// 存储分配失败if (!Q){exit(OVERFLOW);}Q->base = (int *)malloc(MAX_QSIZE * sizeof(int));// 存储分配失败if (!Q->base){exit(OVERFLOW);}Q->front = Q->rear = 0;return Q;
}

(3)入队操作

图2.4-2 入队操作

代码实现如下:

// 插入元素e为Q的新的队尾元素
int Q_Put(SqQueue *Q, int e) {if ((Q->rear + 1) % MAX_QSIZE == Q->front) // 队列满return -1;Q->base[Q->rear] = e;Q->rear = (Q->rear + 1) % MAX_QSIZE;return 1;
}

(4)出队操作

图2.4-3 出队操作

// 若队列不空,则删除Q的队头元素,用e返回其值,并返回1;否则返回-1
int Q_Poll(SqQueue *Q, int &e) {if (Q->front == Q->rear) // 队列空return -1;e = Q->base[Q->front];Q->front = (Q->front + 1) % MAX_QSIZE;return 1;
}

(5)全部源码

注:这里我太懒了没有敲、源码来自于百度

// 队列的顺序存储结构(循环队列)
#define MAX_QSIZE 5 // 最大队列长度+1
typedef struct {int *base; // 初始化的动态分配存储空间int front; // 头指针,若队列不空,指向队列头元素int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;// 构造一个空队列Q
SqQueue* Q_Init() {SqQueue *Q = (SqQueue*)malloc(sizeof(SqQueue));// 存储分配失败if (!Q){exit(OVERFLOW);}Q->base = (int *)malloc(MAX_QSIZE * sizeof(int));// 存储分配失败if (!Q->base){exit(OVERFLOW);}Q->front = Q->rear = 0;return Q;
}// 销毁队列Q,Q不再存在
void Q_Destroy(SqQueue *Q) {if (Q->base)free(Q->base);Q->base = NULL;Q->front = Q->rear = 0;free(Q);
}// 将Q清为空队列
void Q_Clear(SqQueue *Q) {Q->front = Q->rear = 0;
}// 若队列Q为空队列,则返回1;否则返回-1
int Q_Empty(SqQueue Q) {if (Q.front == Q.rear) // 队列空的标志return 1;elsereturn -1;
}// 返回Q的元素个数,即队列的长度
int Q_Length(SqQueue Q) {return (Q.rear - Q.front + MAX_QSIZE) % MAX_QSIZE;
}// 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
int Q_GetHead(SqQueue Q, int &e) {if (Q.front == Q.rear) // 队列空return -1;e = Q.base[Q.front];return 1;
}// 打印队列中的内容
void Q_Print(SqQueue Q) {int p = Q.front;while (Q.rear != p) {cout << Q.base[p] << endl;p = (p + 1) % MAX_QSIZE;}
}// 插入元素e为Q的新的队尾元素
int Q_Put(SqQueue *Q, int e) {if ((Q->rear + 1) % MAX_QSIZE == Q->front) // 队列满return -1;Q->base[Q->rear] = e;Q->rear = (Q->rear + 1) % MAX_QSIZE;return 1;
}// 若队列不空,则删除Q的队头元素,用e返回其值,并返回1;否则返回-1
int Q_Poll(SqQueue *Q, int &e) {if (Q->front == Q->rear) // 队列空return -1;e = Q->base[Q->front];Q->front = (Q->front + 1) % MAX_QSIZE;return 1;
}

三、经典实例

3.1 层次遍历

在信息处理中有一大类问题需要逐层或逐行处理。这类问题的解决方法往往是在处理当前层 或当前行时就对下一层或下一行做预处理,把处理顺序安排好,等到当前层或当前行处理完毕,就可以处理下一层或下一行。

使用队列是为了保存下一一步的处理顺序。下面举一个二叉树层次遍历的例子

图 3.1-1 二叉树

图 3.1-2  二叉树遍历过程

该过程的简单描述如下:

1. 根节点入队

2. 若队空(所有节点均处理完毕),结束。否则重复3.

3. 队列中第一个结点出队,并访问之。若其有左孩子,若其有右孩子,则将右孩子入队,返回2.

3.2 队列在计算机系统中的应用

队列在计算机系统中的应用非常广泛,以下仅从两个方面来简述队列在计算机系统中的作 用:

1. 第一个方面是解决主机与外部设备之间速度不匹配的问题,

2. 第二个方面是解决由多用户引起 的资源竞争问题。

对于第一个方面,仅以主机和打印机之间速度不匹配的问题为例做简要说明。主机输出数据 给打印机打印,输出数据的速度比打印数据的速度要快得多,解决的方法是设置一个打印数据缓冲区,主机把要打印输出的数据依次写入这个缓冲区,写满后就暂停。打印机就从缓冲区中按照先进先出的原则依次取出数据并打印,打印完后再向主机发出请求。主机接到请求后再向缓冲区写入打印数据。打印数据缓冲区中所存储的数据就是一个队列。

对于第二个方面,CPU 资源的竞争就是一个典型的例子。在一个带有多终端的计算机系统上,有多个用户需要CPU各自运行自己的程序,它们分别通过各自的终端向操作系统提出占用CPU的请求。操作系统通常按照每个请求在时间上的先后 顺序,把它们排成一个队列,每次把CPU分配给队首请求的用户使用。当相应的程序运行结束或 用完规定的时间间隔后,令其出队,再把CPU分配给新的队首请 个用户的请求,又使CPU能够正常运行。

3.3 其他实例

其他的实例还包含:划分子集问题、农夫过河问题、离散事件模拟、作业调度、迷宫问题。

在这里不再列举,大家可以自行搜索。

四、小结:栈与队列

本章介绍了两种特殊的线性表:栈和队列,主要内容如下。

(1) 栈是限定仅在表尾进行插入或删除的线性表,又称为后进先出的线性表。栈有两种存储表示,顺序表示(顺序栈)和链式表示(链栈)。栈的主要操作是进栈和出栈,对于顺序栈的进栈 和出栈操作要注意判断栈满或栈空。

(2) 队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素。 队列也有两种存储表示,顺序表示(循环队列)和链式表示(链队)。队列的主要操作是进队和出 队,对于顺序的循环队列的进队和出队操作要注意判断队满或队空。凡是涉及队头或队尾指针的 修改都要将其对MAXQSIZE求模。

(3) 栈和队列是在程序设计中被广泛使用的两种数据结构,其具体的应用场景都是与其表示 方法和运算规则相互联系的。下表分别从逻辑结构、存储结构和运算规则三方面对二者进行了比较。

队列

比较项目

队列

逻辑结构 和线性表一样,元素之间存在一对一的关系 和线性表一样,元素之间存在一对一的关系

存储结构

顺序存储:

存储空间预先分配,可能会导致空间闲置或 栈满溢出现象;数据元素个数不能自由扩充

顺序存储(常设计成循环队列形式):

存储空间预先分配,可能会导致空间闲置或 队满溢出现象;数据元素个数不能自由扩充

链式存储:

动态分配,不会出现闲置或栈满溢出现象; 数据元素个数可以自由扩充

链式存储:

动态分配,不会出现闲置或队满溢出现象; 数据元素个数可以自由扩充

运算规则

插入和删除在表的一端(栈顶)完成,后进先出

插入运算在表的一端(队尾)进行,删除运算在表的另一端(队头),先进先出

(4)栈有一个重要应用是在程序设计语言中实现递归。递归是程序设计中最为重要的方 法之一,递归程序结构清晰,形式简洁。但递归程序在执行时需要系统提供隐式的工作栈来 保存调用过程中的参数、局部变量和返回地址,因此递归程序占用内存空间较多,运行效率较低。

考研复习之数据结构(六)栈和队列(下)(包含队列的相关内容、栈和队列的对比以及总结)相关推荐

  1. 考研复习之数据结构笔记(五)栈和队列(上)(包含栈的相关内容)

    目录 一.栈的定义 1.1相关概念与特点 (1)相关概念 (2)相关特点 (3)栈的运算 (4)顺序栈和链式栈的区别 二.栈的表示和实现 2.1顺序栈的表示和实现 (1)结构体定义 (2)建立空栈 ( ...

  2. 考研复习之数据结构笔记(九)树(上)(树和二叉树的概念、特征、性质及相关实例)

    目录 一.树的基本概念和术语 1.1 基本定义与特点 (1)基本定义: (2)基本特点 1.2 树的基本术语 1.3 树的基本性质 二.二叉树 2.1 二叉树的定义与性质 (1)基本概念 (2)与树的 ...

  3. 考研复习之数据结构笔记(十二)图(下)(图的应用,包含最小生成树、最短路径、拓扑排序、关键路径以及单元小结)

    目录 一.图的应用 1.1 最小生成树 (1)基本概念与问题引入 (2)Prim(普里姆)算法 (3)Kruskal(克鲁斯卡尔)算法 1.2 最短路径 (1)基本概念与问题引入 (2)Dijkstr ...

  4. 2022年王道数据结构考研复习指导习题代码(栈和队列)

    3.1栈 1.写出一个算法,判定所给的操作序列是否合法.若合法,返回true,否则返回false(假定被判定的操作序列已存入一维数组中). #include <stdio.h> #incl ...

  5. 数据结构【考研复习规划】

    数据结构[考研复习规划] 一.线性表 1.线性表 2.线性表的顺序表示和实现 3.线性表中顺序表的初始化 二.栈和队列 三.串.数组和广义表 四.树和二叉树 五.图 六.查找 七.排序 准备要考研了, ...

  6. 823专业课计算机,辽宁科技大学823计算机专业基础综合(含数据结构、计算机组成原理、操作系统和计算机网络)考研复习经验...

    考研是一场持久战,在辽宁科技大学823计算机专业基础综合(含数据结构.计算机组成原理.操作系统和计算机网络)考研复习的过程中,难免会遇到各种各样的问题和挑战.在进入强化冲刺阶段之后,高强度的学习和心里 ...

  7. 浙大计算机科学基础题型,浙江大学878计算机学科专业基础(含数据结构)考研复习经验...

    考研是一场持久战,在浙江大学878计算机学科专业基础(含数据结构)考研复习的过程中,难免会遇到各种各样的问题和挑战.在进入强化冲刺阶段之后,高强度的学习和心里压力更是让很多学子身心疲惫!如何少走弯路, ...

  8. 数据结构(c语言版)笔记6,2020考研计算机《数据结构(C语言版)》复习笔记(6)

    2020年计算机考研复习已经开始,新东方在线在此整理了2020考研计算机<数据结构(C语言版)>复习笔记(6),希望能帮助大家! 第六章 树知识点整理 树是n个结点的有限集合,非空时必须满 ...

  9. 数据结构数组计算机中的应用,2018考研计算机:数据结构数组和广义表复习重点...

    2018考研计算机:数据结构数组和广义表复习重点 2017-08-17 16:00 | 考研集训营 <数据结构(C语言版)>复习重点在二.三.六.七.九.十章,考试内容两大类:概念,算法, ...

最新文章

  1. UIView 的 autoresizingMask 属性 详解。
  2. hdu 1175 连连看
  3. 读书笔记 effective c++ Item 18 使接口容易被正确使用,不容易被误用
  4. 19生成材料清单_SOLIDWORKS 钣金装配体材料明细表扩展应用
  5. mysql 5.6 ddl 锁表_MySQL数据库之MySQL5.6 Online DDL 是否锁表、rebuild表、inplace的说明...
  6. 梯度下降法参数更新公式的推导
  7. 让孩子从小自信的28个方法
  8. css的position属性取值
  9. 精品、好用、优质、黑科技网站推荐
  10. css给div四角添加效果
  11. Linux 修改hosts文件
  12. 计算机任务管理器设置软件启动,电脑软件开机自动启动,教你一招禁止启动,能够有效提升开机速度...
  13. 初学Python——协程
  14. NVM(NonVolatile Memory)(非易失性内存)
  15. Apollo-阿波罗配置中心详细使用教程
  16. java path 注解_Java内置系统注解和元注解
  17. tcl/tk 的原生界面
  18. 《周志明的软件架构课》学习笔记 Day6
  19. 怎样把ppt图片完整的转换成pdf
  20. 制作CPA静默安装包和静默包软件捆绑方法

热门文章

  1. 海康SDK 通过java接口设置和获取摄像机参数
  2. IT技术学习指导之Linux系统入门的4个阶段
  3. Fresco的使用一
  4. 文加图, 理解Http请求与响应
  5. OD-Model【2】:Fast R-CNN
  6. 当你疲惫时,准备放弃时,看看这个
  7. android输入算法,词库+智能算法才是王道 Android输入法对比
  8. 技术总监送给刚毕业的程序员——7点建议
  9. 这里以Amlogic A113
  10. 字节跳动+京东+360+网易面试题整理,Java岗