实验内容:火车车厢重排问题。

实验内容:火车车厢重排问题。

实验说明:

转轨站示意图如下:

火车车厢重排算法伪代码如下:

1. 分别对k个队列初始化;

2. 初始化下一个要输出的车厢编号nowOut = 1;

3. 依次取入轨中的每一个车厢的编号;

3.1 如果入轨中的车厢编号等于nowOut,则

    3.1.1 输出该车厢;

    3.1.2  nowOut++;

3.2 否则,考察每一个缓冲轨队列

    for (j=1; j<=k; j++)

 3.2.1 取队列 j 的队头元素c;

 3.2.2 如果c=nowOut,则

      3.2.2.1 将队列 j 的队头元素出队并输出;

    3.2.2.2  nowOut++;

3.3 如果入轨和缓冲轨的队头元素没有编号为nowOut的车厢,则

    3.3.1 求小于入轨中第一个车厢编号的最大队尾元素所在队列编号j;

3.3.2 如果 j 存在,则把入轨中的第一个车厢移至缓冲轨 j;

实验过程

  • 队列的基本算法实现

其中包含一些要实现火车车厢排列问题的必要基本算法实现,这几种算法的时间复杂度均为O(1)。

  1. #include<stdio.h>
  2. using namespace std;
  3. #define MaxSize 100
  4. typedef int ElemType;
  5. typedef struct SqQueue{
  6.  ElemType data[MaxSize];//存放队中的元素
  7.  int front, rear;//队头和队尾指针
  8. }SqQueue;//顺序队类型
  9. void InitQueue(SqQueue*& q) {//初始化队列
  10.  q = new SqQueue;
  11.  q->front = q->rear =-1;
  12. }
  13. bool EnQueue(SqQueue*& q, ElemType e) {//进队列
  14.  if (q->rear == MaxSize - 1)//堆满上溢出
  15.   return 0;
  16.  q->data[q->rear] = e;
  17.  q->rear++;
  18.  return 1;
  19. }
  20. bool DeQueue(SqQueue*&q, ElemType& e) {//出队列
  21.  if (q->front == q->rear)//堆满下溢出
  22.   return 0;
  23.  e = q->data[q->front];
  24.  q->front++;
  25.  return 1;
  26. }
  27. bool GetFront(SqQueue* q, ElemType& num) {//获取队头元素
  28.  if (q->front == q->rear)
  29.   return false;
  30.  num = q->data[q->front];
  31.  return true;
  32. }
  33. bool GetRear(SqQueue* q, ElemType& num) {//获取队尾元素
  34.  if (q->front == q->rear)
  35.   return false;
  36.  num = q->data[q->rear-1];
  37.  return true;
  38. }
  • 重排和主函数

就算火车车厢的顺序打乱了之后,其编号也是连续的,可以利用这个点,所以我们定义三个队列:H1、H2、H3,将打乱的序列入队进H3,同时定义一个nowOut=1,让其自增,遍历序列H3,如当前遍历元素等于nowOut,那就将该元素出队,nowOut自增,否则就去H1和H2队列的对头去找有无等于nowOut的元素,若H1、H2、H3都没有nowOut,那么就将当前遍历的元素放进H1或H2条件是该元素必须大于H1或H2的队尾元素,如此循环完毕,最终可输出排列好的序列。

算法的时间复杂度均为O(nlog2n),n为火车车厢的长度。

  1. int main() {
  2.  SqQueue* h1, * h2, * h3;//创建队列,相当于三条铁轨
  3.  InitQueue(h1);
  4.  InitQueue(h2);
  5.  InitQueue(h3);
  6.  SqQueue* Array[] = { h1,h2,h3 };//指向结构体的指针数组
  7.  cout << "输入车厢号,输入0停止" << endl;
  8.  while (1) {//先将元素入队h3
  9.   int n;
  10.   cin >> n;
  11.   if (n == 0)
  12.    break;
  13.   EnQueue(h3, n);
  14.  }
  15.  int nowOut = 1;//下一个输出的车厢编号,最开始为1
  16.  cout << "排序后" << endl;
  17.  while (h1->front < h1->rear || h2->front < h2->rear || h3->front < h3->rear) {
  18.   //所有队列全为空时,退出循环
  19.   int flag = 0;//为0时,表示入轨和缓冲轨对头都没有编号为nowOut的车厢
  20.   //为1,表示在入轨和缓冲轨队头找到编号为nowOut的车厢
  21.   int num;
  22.   GetFront(h3,num);//获取入轨的队头元素
  23.   if (num == nowOut) {//与nowOut一样时,直接出队列
  24.    DeQueue(h3, num);
  25.    nowOut++;
  26.    cout << num<<" ";
  27.    flag = 1;
  28.   }
  29.   else {
  30.    for (int i = 0; i < 2; i++) {//在缓冲队列中找
  31.     GetFront(Array[i], num);
  32.     if (num == nowOut) {
  33.      DeQueue(Array[i], num);
  34.      nowOut++;
  35.      cout << num<<" ";
  36.      flag = 1;
  37.     }
  38.    }
  39.   }
  40.   if (flag == 0) {//入轨和缓冲轨中都没有
  41.    int a;
  42.    for (int i = 0; i < 2; i++) {//求小于入轨中第一个车厢编号的最大队尾元素所在队列编号
  43.     GetFront(h3, num);
  44.     GetRear(Array[i], a);
  45.     if (num > a || Array[i]->rear == -1) {
  46.      //如果存在,则把入轨中的第一个车厢移至缓冲轨
  47.      DeQueue(h3, num);
  48.      EnQueue(Array[i], num);
  49.      break;
  50.     }
  51.     else if(i==1){//轨道数量太少,没有解决的办法
  52.      cout << "没有解决的办法" << endl;
  53.      return 0;
  54.     }
  55.    }
  56.   }
  57.  }
  58.  return 0;
  59. }

执行结果

总结

队列相当于一种操作限制的线性表,只能在一端进行插入操作,另一端进行删除操作,被称为先进先出表。队列通常作为一种存放临时变量的容器,如果先存入的元素先处理,就可采用队列。该算法中用到的队列是线性存储结构,只要在出队入队操作中稍加修改,就会变成环形队列。当火车车厢是任意打乱顺序的排列,两条缓冲轨是无法解决整个问题的,需要多添加几个轨道,也就是多定义队列来解决这个问题

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值