zoukankan      html  css  js  c++  java
  • 队列问题非STL解决方案

    队列问题非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;
    }
    

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

  • 相关阅读:
    (转)【web前端培训之前后端的配合(中)】继续昨日的故事
    ural(Timus) 1136. Parliament
    scau Josephus Problem
    ACMICPC Live Archive 6204 Poker End Games
    uva 10391 Compound Words
    ACMICPC Live Archive 3222 Joke with Turtles
    uva 10132 File Fragmentation
    uva 270 Lining Up
    【转】各种字符串哈希函数比较
    uva 10905 Children's Game
  • 原文地址:https://www.cnblogs.com/izwb003/p/queue-no-STL-solution.html
Copyright © 2011-2022 走看看