火车车厢重排列问题
问题描述:一列货运列车共有n节车厢,每节车厢将停放在不同的车站.假定n个车站的编号为1--n,即货运列车按照第n站至第1站的次序经过这些车站。为了便于列车卸掉相应的车厢,车厢的编号应与车站的编号相同。使各个车厢按1~n次序排列,这样每次卸掉最后一节车厢即可.所以给定任意次序的车厢,必须重排列它们.可排列的地方是转轨站,转轨站由一个入轨站,一个出轨站,缓冲轨k个.列车由入轨站进站,经过缓冲轨,出轨.开始时,n节车厢从入轨进入入轨站,转轨结束后按照1-n的次序出轨.假定缓冲轨具有先进先出的特性,且禁止将车厢从缓冲轨移址入轨,将出轨移至缓冲轨.假设有k个缓冲轨,则可以用来暂存车厢的为k-1个,另一个直接出轨.
分析:将车厢C移至缓冲轨时,应该移到这样的缓冲轨:队尾元素小于车厢C,如果有多个这样的缓冲轨,选择队尾元素最大的;否则,选择一个空的缓冲轨.将定有n节车厢,初始排列次序已定,给定k个缓冲轨,用nowOut表示当前到出轨的车厢序号,则有火车厢重排列伪算法如下:
1.初始化k个队列;
2.置nowOut为初始值1,依次取出火车车厢元素与newOut比较:
1)如果newOut == 元素:
输出车厢序号;
newOut++;
2)否则,考察每个缓冲区队列
for(int i = 0; i<k; i++)
1)取队列头元素C:
如果c == newOut;出列,NewOut++;
如果没有队头元素 == newOut:
求小于入轨车厢编号的最大队尾元素所在队列j;
问题描述:一列货运列车共有n节车厢,每节车厢将停放在不同的车站.假定n个车站的编号为1--n,即货运列车按照第n站至第1站的次序经过这些车站。为了便于列车卸掉相应的车厢,车厢的编号应与车站的编号相同。使各个车厢按1~n次序排列,这样每次卸掉最后一节车厢即可.所以给定任意次序的车厢,必须重排列它们.可排列的地方是转轨站,转轨站由一个入轨站,一个出轨站,缓冲轨k个.列车由入轨站进站,经过缓冲轨,出轨.开始时,n节车厢从入轨进入入轨站,转轨结束后按照1-n的次序出轨.假定缓冲轨具有先进先出的特性,且禁止将车厢从缓冲轨移址入轨,将出轨移至缓冲轨.假设有k个缓冲轨,则可以用来暂存车厢的为k-1个,另一个直接出轨.
分析:将车厢C移至缓冲轨时,应该移到这样的缓冲轨:队尾元素小于车厢C,如果有多个这样的缓冲轨,选择队尾元素最大的;否则,选择一个空的缓冲轨.将定有n节车厢,初始排列次序已定,给定k个缓冲轨,用nowOut表示当前到出轨的车厢序号,则有火车厢重排列伪算法如下:
1.初始化k个队列;
2.置nowOut为初始值1,依次取出火车车厢元素与newOut比较:
1)如果newOut == 元素:
输出车厢序号;
newOut++;
2)否则,考察每个缓冲区队列
for(int i = 0; i<k; i++)
1)取队列头元素C:
如果c == newOut;出列,NewOut++;
如果没有队头元素 == newOut:
求小于入轨车厢编号的最大队尾元素所在队列j;
如果j存在,将其放入j队列;否则,查看是否有空缓冲区,否则车厢无法重排列.
源码实现,本例应用了前面实现的链队列,关于链队列实现请参照前面的章节:
bool RearrangeMent(int array[], int nLen, int BufferCount)
{
if (nLen <= 0 || BufferCount <= 0)
{
return false;
}
// 初始化BufferCount个缓冲轨队列
CLinkQueue<int>* pQueueArray = new CLinkQueue<int>[BufferCount];
int newOut = 1;
int j = nLen - 1;
while (newOut<=nLen) // 直到最大的车厢出轨
{
if (j >=0 && array[j] == newOut) // 如果当前火车序号是要出的序号,直接出轨
{
printf("%d, ", newOut);
newOut++;
j--;
}else // 否则,循环判断每个队列头元素
{
bool bQueueHave = false;
for (int k = 0; k<BufferCount; k++)
{
if (!pQueueArray[k].Empty())
{
int front = pQueueArray[k].GetQueue();
if (front == newOut) // 头元素是要出的车厢,出列.
{
pQueueArray[k].DeQueue();
printf("%d, ", front);
newOut++;
bQueueHave = true;
break;
}
}
}
if(j >= 0 && !bQueueHave)// 没有符合条件的元素,找到此车厢需要放入的队列
{
int nMax = 0;
int nQueue = -1; // 应该入的队列
for (int m = 0; m<BufferCount; m++)
{
if (!pQueueArray[m].Empty())
{
int Dis = array[j] - pQueueArray[m].GetRear();
if (Dis > 0 && Dis>nMax)
{
nMax = Dis;
nQueue = m;
}
}
}
bool bFind = false; // 是否存在空队列容纳此元素
if (nQueue != -1) // 找到队列入队
{
pQueueArray[nQueue].EnQueue(array[j]);
j--;
continue;
}else
{
for (int n = 0; n<BufferCount;n++)
{
if (pQueueArray[n].Empty())
{
bFind = true;
pQueueArray[n].EnQueue(array[j]);
j--;
break;
}
}
}
if (!bFind)
{
return false;
}
}
}// else
} // while
delete[] pQueueArray;
return true;
}
测试代码:
int array[] = {5,8,1,7,4,2,9,6,3};
RearrangeMent(array, sizeof(array)/sizeof(int), 2);
输出结果: