队列问题非STL解决方案


常年使用STL解决队列问题,以至于严重生疏队列的根本原理。。。

直到今日 被老师被迫 使用算法原理解决问题,方才意识到我对队列一窍不通。。。

。。。直到 经过一系列的坑蒙拐骗 之后,方才理清楚一些头绪,在此附记。

有关概念在此不再赘述,因为这东西怕不是一搜一大堆。。。


循环队列——数组存储方案:

我们需要的东西:

1.一个数组,拿来存队列。

int ique[capa];//capa是数组(队列)的最大容量,看下面↓

2.头指针及尾指针,指明队列的头和尾。

int	ihead=0,itail=0;

3.再来两个量——队列的当前长度(是变量)及其最大容量(是常量,在开数组时已经界定,这里为演示开的短一些,只开到4)

int ilen=0;
const int capa=4;

接下来是一些基本的操作:

1.将elem入队:

int elem;
ique[itail]=elem;//尾指针始终指向队列尾部的下一个位置,因此我们只需将尾指针处的数字做出更改即可。
itail++;//尾指针自增,指向下一个位置。
itail=itail % capa;//圈重点,见下↓
ilen++;//因为多了一个元素而长度增加,使ilen自增。

itail=itail % capa;

我们一直在使尾指针自增,而数组的长度只有4。 在这里通过取余即可实现循环入队。这样当尾指针增大到capa以外时,通过该语句即可自动使尾指针跳转回数组的开头,实现循环读入、循环存储。

在这里尾指针始终指向队列尾部的下一个位置,使其指向队列尾部那个元素的原理是相同的。

2.出队,存入elem:

int elem;
elem=ique[ihead];//直接取出头指针处的元素
ihead++;//头指针往下移动
ihead=ihead % capa;//和上面同理
ilen--;//因为少了一个元素而长度减少,使ilen自减。

比较关键的操作就在于将指针对capa取余,这样的操作可以使指针形成循环,也就实现了队列的循环存储。在其他地方如果我们需要用到循环存储,对其容量取余是个很好的思路。当然实际应用中其大小不仅仅是4这么少,我们还应该留意数据范围合理安排空间,要不出现了塞不下或者空太多的问题都是很辣手棘手的。

基本的操作就是这样 (是不是很简单) (是不是理解起来有些难) (还是本来就挺简单被我给说难了。。。)


举个例子:

洛谷P1996 约瑟夫问题

题目:

n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.

输入格式

n m

输出格式

出圈的编号

输入样例

10 3

输出样例

3 6 9 2 7 1 8 5 10 4

说明

m,n≤100

-->用STL的话基本不用动脑,5分钟搞定。如下:

#include<queue>//队列所必须的头文件
#include<cstdio>
using namespace std;
queue <int> set;//创建该队列
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
set.push(i);//把各个人的编号入队准备报数
}
int counti=1;//报数的计数器
while(!set.empty())
{
if(counti!=m)
{
set.push(set.front());//不是m,循环将队头塞进队尾,实现循环
set.pop();
}
if(counti==m)
{
printf("%d ",set.front());//是m这个人出列,将其编号输出后出队
set.pop();
counti=1;//再次从1开始
continue;//继续
}
counti++;
}
return 0;
}

不使用STL的话,构建队列就要稍微麻烦一些,不过能更好的理解其原理及应用。然而无论如何STL都只是个工具,我们必要应该掌握的还是其实现原理。下面是无STL的解决方案:

//luogu.org P1996 -- NO STL Solution
//queue--Array Solution //IZWB003-2019/07/24 #include<cstdio> //set queue//设置该队列
int head=0,tail=0;//指针2个
int length=0;const int capacity=120;//大小及长度
int queue[capacity];//通过数组储存队列
int element; using namespace std;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
queue[tail]=i+1;//尾指针处入队
tail++;
tail=tail%capacity;//上面的方法
length++;//改长度
}
int i=0;//以i作为报数的计数器
while(true)
{
element=queue[head];//头指针处出队
head++;
head=head%capacity;//上面的方法
length--;//改长度
i++;//报数
if(i==m)//该出队处
{
printf("%d ",element);//输出
i=0;//重新报数
}
else//不符合则接着入队
{
queue[tail]=element;
tail++;
tail=tail%capacity;
length++;
}
if(length==0) break;//队空则结束
}
return 0;
}

有关链表建队列的相关知识,有时间的话,稍后补充。

队列问题非STL解决方案的更多相关文章

  1. 标准非STL容器 : bitset

    1. 概念 什么是"标准非STL容器"?标准非STL容器是指"可以认为它们是容器,但是他们并不满足STL容器的所有要求".前文提到的容器适配器stack.que ...

  2. 探讨SQL Server并发处理队列数据不阻塞解决方案

    前言 之前对于并发这一块确实接触的比较少,自从遇到现在的老大,每写完一块老大都会过目一下然后给出意见,期间确实收获不少,接下来有几篇会来讲解SQL Server中关于并发这一块的内容,有的是总结,有的 ...

  3. java阻塞队列与非阻塞队列

    在并发编程中,有时候需要使用线程安全的队列.如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法. //使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入 ...

  4. 蓝桥 ADV-233 算法提高 队列操作 【STL】

      算法提高 队列操作   时间限制:1.0s   内存限制:256.0MB      问题描述 队列操作题.根据输入的操作命令,操作队列(1)入队.(2)出队并输出.(3)计算队中元素个数并输出. ...

  5. Windows消息理解(系统消息队列,进程消息队列,非队列消息)

    // ====================Windows消息分类==========================在Windows中,消息分为以下三类:标准消息——除WM_COMMAND之外,所 ...

  6. HDU 4280Island Transport(Dinc非STL 模板)

    题意: n岛m条路,然后是 n个岛的坐标,然后是m条双向路,包括 岛和 岛 之间 最大客流量,让求 最左边的岛 到右边的岛 最大客流量 分析: 建图 以 左边的岛为原点,最右边的为终点求最大客流量. ...

  7. calc 多项式计算 (STL版和非STL版) -SilverN

    计算(calc.cpp) [问题描述] 小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“)”,“0-9”,“+”,“-”,“*” ...

  8. 栈和队列简单的STL模板

    栈的使用,可以想象成是只有一个出口,最后进来的那个最先出去: #include <stack> 队列:是有两个出口,但是进来了之后只能从前门出去,也就是最先进来的那个最后出去: #incl ...

  9. win10每次开机都会自检系统盘(非硬件故障)——解决方案2019.07.12

    1.最近反复遇到了这个问题,之前遇到这个问题就把系统重装了,没想到今天又遇到了,目前系统东西太多了,重装太麻烦了,就下决心解决一下. 2.不要使用网络上流传的修改注册表的方案,把注册表的那个键值删除那 ...

随机推荐

  1. Oracle DBA_EXTENTS视图 与 DBA_SEGMENTS视图

    DBA_EXTENTS describes the extents comprising the segments in all tablespaces in the database.   Note ...

  2. 【JAVA】Java 异常中e的getMessage()和toString()方法的异同

    参考链接 CSDN: Java 异常中e的getMessage()和toString()方法的异同 示例代码1: public class TestInfo {     private static ...

  3. NIO的缓冲区、通道、选择器关系理解

    Buffer的数据存取    一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类.   Java NIO中的Buffer主要用于与NIO通道进行交互,数 ...

  4. SQL语句分类

    SQL Structured Query Language SQL是结构化查询语言,是一种用来操作RDBMS的数据库语言,当前关系型数据库都支持使用SQL语言进行操作,也就是说可以通过 SQL 操作 ...

  5. Google Capture The Flag 2018 (Quals) - Beginner's Quest - Reverse - Firmware

    参考链接:https://ctftime.org/task/6263 题目 After unpacking the firmware archive, you now have a binary in ...

  6. php 调用远程url

    // ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. // ; http://php.net/a ...

  7. python tkinter实时显示曲线

    from tkinter import *from tkinter import ttkimport time#画窗口root = Tk()root.geometry('1000x500')root. ...

  8. redis专题

    1.Linux安装redis 2.redis持久化 3.redis配置 4.SpringBoot整合Redis发布订阅 5.redis事务 5.1.redis事务介绍 5.2. redisTempla ...

  9. JavaWeb(八):Filter和Listener

    一.Filter 1.1 概述 Filter 的基本功能是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊的功能.在 Servlet ...

  10. 026:if标签使用详解

    if标签使用详解: if 标签: if 标签相当于 Python 中的 if 语句,有 elif 和 else 相对应,但是所有的标签都需要用标签符号  {%  %}  进行包裹. if 标签中可以使 ...