数据结构-------列车重排-----队列的应用

本文介绍了如何利用数据结构中的队列解决列车车厢重排问题。通过多个队列模拟缓冲轨道,确保车厢按照编号顺序出站。代码实现中包含队列的创建、入队、出队等操作,展示了队列在解决实际问题中的应用。
摘要由CSDN通过智能技术生成
一、 问题说明
                 一列货运列车共有n节车厢,每节车厢将停放在不同的车站。假定n个车站的编号分别为1~n,货运列车按照第n站至第1站的顺序经过这些车站。车厢编号与他们的目的地一样。为了便于从列车上卸掉相应的车厢,必须重排车厢顺序,使得各车厢从前往后按编号1到n的次序排列。当所有车厢按照这种次序排列时,在每个车站只需卸掉最后一个车厢即可。
二、方法
        采用多个队列,应用队列先进先出的特点
假设有9个车厢,先假设有一个(k = 1)缓冲轨道,求是否能将列车重排,若不能,就k++,直到k = 8,一定可以将它重排,这样从1增加到8,一旦重排成功,就return,结束程序,得出最少需要的缓冲轨道。
代码中用NowOut表示当前应该输出的车厢编号,minH表示缓冲轨道中编号最小的车厢编号,minQ表示最小编号的车厢所在缓冲轨道的编号(0号轨道是不用的)
遍历数组元素,若当前数组元素等于NowOut时,直接输出该车厢到出轨,然后NowOut++,检测当前各个缓冲轨道的队首元素是否等于NowOut,是的话,直接将此编号车厢输出到出轨,重置minH和minQ,然后NowOut++,这样一直检测输出。不等于NowOut就不输出,并退出循环。若当前数组元素不等于NowOut,就将此元素进入一个最适合的队列中,具体方法看代码。
三、代码实现
#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
typedef struct QType
{
    int number;
}QType;

typedef struct Queue
{
    QType *element;
	int front;
	int rear;
	int maxsize;
}Queue;
//主体为一个以数组为存储对象的循环队列,其中Q[0]不存放数据
void CreatQueue(Queue &Q,int MaxQueueSize);//初始化队列函数声明
bool EnQueue(Queue &Q,QType &x);//元素入队
bool DeQueue(Queue &Q,QType &x);//元素出队
bool GetFront(Queue &Q,QType &x);//获取front指向的元素值
bool GetRear(Queue &Q,QType &x);//获取rear指向的元素值
bool IsEmpty(Queue &Q);//判断队列是否为空
bool IsFull(Queue &Q);//判断队列是否满
bool RearrangementTrack(int r[],int n,int k);
void Output(int &minH,int &minQ,Queue Q[],int k,int n);
bool Hold(int current ,int &minH,int &minQ,Queue Q[],int k,int n);

int main()
{
    int a[9] = {9,8,7,6,2,3,5,4,1};
    int k;
	for(k=1;k<=8;k++)
	{
	   if(!RearrangementTrack(a,9,k))
	   {
	      system("cls");//若缓冲轨道不够,就清屏
	   }
	   else
	   {
		  printf("缓冲轨道最少要%d个\n",k-1);//因为0号轨道不用,所以为k-1
		  exit(0);//找到最少缓冲轨道就结束
	   }
	}
	return 0;
}

void CreatQueue(Queue &Q,int MaxQueueSize)
{
    Q.maxsize = MaxQueueSize;
	Q.element = new QType[Q.maxsize+1];
	Q.front = Q.rear = 0;
}

bool IsFull(Queue &Q)
{
   if(Q.front == (Q.rear+1)%(Q.maxsize+1))//当front=rear+1时,队列满
	   return true;
   return false;
}

bool EnQueue(Queue &Q,QType &x)//进队时将rear往前移
{
   if(IsFull(Q))
	   return false;
   Q.rear = (Q.rear+1)%(Q.maxsize+1);
   Q.element[Q.rear] = x;
   return true;
}

bool DeQueue(Queue &Q,QType &x)//出队时将front往前移
{
   if(IsEmpty(Q))
	   return false;
   Q.front = (Q.front+1)%(Q.maxsize+1);
   x = Q.element[Q.front];
   return true;
}

bool GetFront(Queue &Q,QType &x)
{
   if(IsEmpty(Q))
	   return false;
   x = Q.element[(Q.front+1)%(Q.maxsize+1)];
   return true;
}

bool GetRear(Queue &Q,QType &x)
{
   if(IsEmpty(Q))
	   return false;
   x = Q.element[Q.rear];
   return true;
}

bool IsEmpty(Queue &Q)
{
   if(Q.front == Q.rear)
	   return true;
   return false;
}

bool RearrangementTrack(int r[],int n,int k)
{
   Queue *Q = new Queue[k];//创建k个轨道,其中0号缓冲轨道不使用
   int MaxQueueSize = 10;
   for(int i=0;i<k;i++)
   {
      CreatQueue(Q[i],MaxQueueSize);//初始化各个队列
   }
   int NowOut = 1;//一开始,NowOut为1
   int minH = n+1;//这里minH为10
   int minQ;
   for(i = 0;i<n;i++)
   {
      if(r[i] == NowOut)//当前到站的车厢编号刚刚是应该输出的车厢编号,就直接输入出轨
	  {
	     printf("从入轨输出%d号车厢到出轨\n",r[i]);
		 if(NowOut!=n)//判断是否出轨完
			NowOut++;
		 while(minH == NowOut)//从缓冲区输出minH
		 {
		    Output(minH,minQ,Q,k,n);
                    if(NowOut!=n)
			   NowOut++;
		 }
	  }
	  else
	  {
		  if(!Hold(r[i],minH,minQ,Q,k,n))
		  {
		     delete []Q;
			 return false;
		  }
	  }
   }
   delete []Q;//free掉各个队列
   return true;
}

void Output(int &minH,int &minQ,Queue Q[],int k,int n)
{
   int current;
   QType x;
   x.number = minH;
   DeQueue(Q[minQ],x);
   printf("从%d号缓冲铁轨输出%d号车厢到出轨\n",minQ,minH);
   minH = n+1;
   for(int i=1;i<k;i++)
   {//通过检查所有的队列的首部,寻找新的minH和minQ
      GetFront(Q[i],x);
	  current = x.number;
	  if(!IsEmpty(Q[i])&&current<minH)//找到输出minH后缓冲轨道中最小编号的车箱,并给minH、minQ赋值
	  {
	     minH = current;
	     minQ = i;
	  }
   }
}

bool Hold(int current ,int &minH,int &minQ,Queue Q[],int k,int n)
{
   int BestCushion = 0;//表示最优缓冲轨道,0表示没找到最优的
   int BestLast = 0;//BestCushion中最后一节车厢的编号
   QType x;
   for(int i=1;i<k;i++)//扫描缓冲区
   {
      if(!IsEmpty(Q[i]))
	  {
	     GetRear(Q[i],x);
		 if(current > x.number&&x.number > BestLast)//比较current与各个缓冲轨道的最后一个编号
		 {      //若比每一个小且没有空轨道,就返回false(有空轨道,就进入空轨道)
		    BestLast = x.number;//若有几个缓冲轨道的最后一个编号都比current小,那么就找与
			BestCushion = i;//current差最小的缓冲轨道作为最优缓冲轨道入队
		 }
	  }
	  else
	  {
	     if(!BestCushion)//有空轨道就如空轨道(前提是current小于所有缓冲轨道的最后一个编号)
			 BestCushion = i;
	  }
   }
   if(!BestCushion)//最优缓冲轨道没找到,返回false
   {
	   return false;
   }
   x.number = current;
   EnQueue(Q[BestCushion],x);//把current进入最优缓冲轨道
   printf("从入轨将%d号车厢移到%d号缓冲铁轨\n",current,BestCushion);
   if(current < minH)//检查current可否成为新的minH和minQ,如果是,就修改
   {
      minH = current;
	  minQ = BestCushion;
   }
   return true;
}

四、 效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值