杭电数据结构课程实践-车厢调度

车厢调度

      • 需求分析
      • 概要设计
      • 详细设计
      • 程序流程图
      • 测试数据

需求分析

  一列货运列车共有n节车厢,每节车厢将停放在不同的车站。假定n个车站的编号(由远到近)依次为1-n,即货运列车按照第n站至第1站的次序经过这些车站。为了便于从列车上卸掉相应的车厢,车厢的编号应与车站的编号相同,使各车厢从前至后按编号1-n的次序排序,这样,在每个车站只需卸掉最后一节车厢即可。因此,需要对给定任意次序的车厢进行重新排列。
  实现车厢重新排列的目的,可以通过转轨站来完成,在转轨站中有一个入轨、一个出轨和k个缓冲轨,缓冲轨位于入轨和出轨之间。开始时,任意的n节车厢入轨进入转轨站,转轨结束时各车厢按照编号1至n的次序离开转轨站进入出轨。假定缓冲轨按先进先出的方式运作,可将它们视为k个队列,并且禁止将车厢从缓冲轨移至入轨,也禁止从出轨移至缓冲轨。

概要设计

  基于队列及转轨站两种抽象数据类型,在分别对k个队列初始化、且设当前输出车厢号nowout=1、入轨车厢序号i=0,n节车厢重排的算法大致描述如下:

While(nowout<=n)
{
     
	如果各缓冲轨队列中有队头元素等于nowout
		则输出该车厢;
		nowout++;
	否则,求小于car[i]的最大队尾元素所在队列的编号j;
	如果j存在
		则把car[i]移至缓冲轨j;
	否则
		如果至少有一个空缓冲轨
		则把car[i]移至一 个空缓冲轨;
		否则,车厢无法重排,算法结束。
	i++;
}
车厢已重排,算法结束。

详细设计

  为由于车厢的数量并不确定,为避免溢出,本例采用带头结点的单链表实现队列的抽象数据类型。
  单链表实现的抽象数据LinkQueue.h文档如下:

#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_

//链队列结点结构
struct LinkNode {
     
    QElemType data;
    LinkNode *next;
};

//带头结点的链队列结构 
struct LinkQueue {
     
    LinkNode  *front;         //队头指针
    LinkNode  *rear;          //队尾指针
};

//构造一个空的链队列。
void InitQueue( LinkQueue &Q )
{
     
    Q.front = Q.rear = new LinkNode ;
    Q.front->next = NULL;
}//LinkQueue

//将链队列清空。
void ClearQueue( LinkQueue &Q )
{
     
    LinkNode *p;
    while ( Q.front->next != NULL ) 
    {
     
        p = Q.front->next;
        Q.front->next = p->next;
        delete p;
    }
    Q.rear = Q.front;
}

//链队列结构销毁。
void DestroyQueue( LinkQueue &Q )
{
     
    ClearQueue( Q );  //成员函数Clear()的功能是释放链表中的所有元素结点
    delete Q.front;
    Q.front = Q.rear = NULL;
}

//判链队列是否为空,若为空,则返回true,否则返回false。
bool QueueEmpty( LinkQueue Q ) 
{
     
    return Q.front == Q.rear;
}

//返回链队列中元素个数。
int QueueLength( LinkQueue Q )
{
     
    int i = 0;
    LinkNode *p = Q.front->next;
    while ( p != NULL ) 
    {
     
        i++;
        p = p->next;
    }
    return i;
}

//取链队列队头元素的值。先决条件是队列不空。
QElemType GetHead( LinkQueue &Q )
{
     
    return Q.front->next->data;
}

//取链队列队尾元素的值。先决条件是队列不空。
QElemType GetLast( LinkQueue &Q ) 
{
     
    return Q.rear->data;
}

//链队列入队,插入e到队尾。
void EnQueue( LinkQueue &Q, QElemType e )
{
     
    LinkNode *p;
    p = new LinkNode ;
    p->data = e;
    p->next = NULL;
    Q.rear->next = p;
    Q.rear = p;
}

//链队列出队。先决条件是队列不空。
bool DeQueue( LinkQueue &Q,QElemType &e )
{
        
    if ( QueueEmpty( Q ) ) 
        return false;
    LinkNode *p = Q.front->next;
    Q.front->next = p->next;
    e = p->data;
    if ( p == Q.rear )
	    Q.rear = Q.front;  //若出队后队列为空,需修改Q.rear。
    delete p;
    return true;
}

#endif

  转轨站抽象数据类型的实现,数据结构设计为队列的指针向量,其Realign.h文件如下:

#ifndef _Realign_H_
#define _Realign_H_

#include "LinkQueue.h"
struct	CTrackStation {
     
    LinkQueue *pTracks;  //各缓冲轨(队列)
    int trackCount; //缓冲轨数量
};

//初始化k个轨道 
void InitCTrackStation(CTrackStation &TS,int &k) {
     	
    TS.trackCount = k;
    TS.pTracks = new LinkQueue[ k ];
    for ( int i = 0; i < k; i++ )  
        InitQueue( TS.pTracks[ i ] ); 
}

//销毁k个轨道  
void DestroyCTrackStation( CTrackStation &TS )
{
        
    for ( int i = 0; i < TS.trackCount; i++ )  
        DestroyQueue(TS.pTracks[i]);
    delete[] TS.pTracks;
    TS.trackCount = 0;
}

//将车厢car移到其中一个可用缓冲轨,成功返回true。
bool HoldIn( CTrackStation &TS, int &car, int &k )
{
     
    int bestTrack = - 1;		//目前最优的缓冲轨
    int bestLast = - 1;		//最优缓冲轨中的最后一节车厢
    int i;	
    for ( i = 0; i < TS.trackCount; i++ ) 
    {
     //查找最优缓冲轨
	    if ( ! QueueEmpty( TS.pTracks[ i ] ) ) 
        {
     
		    int last;		//车厢编号
		    last = GetLast( TS.pTracks[ i ] );
		    if(car > last && last > bestLast) 
            {
     //缓冲轨i尾部的车厢号较大
			    bestLast = last;
			    bestTrack = i;
		    }
	    }
    }
    if ( bestTrack == -1 ) 
    {
      //未找到合适缓冲轨,查找空闲缓冲轨 
	    for ( i = 0; i < TS.trackCount; i++ )
		    if ( QueueEmpty( TS.pTracks[ i ] ) ) 
            {
     
			    bestTrack = i;
			    break;
		    }
    }
    if ( bestTrack == -1 ) 
        return false;    //没有可用的缓冲轨
    EnQueue( TS.pTracks[ bestTrack ], car );
    k = bestTrack;//将车厢ca移入k号缓冲轨
    return true;
}

//将缓冲轨中车厢car移出,成功返回true。
bool HoldOut( CTrackStation &TS, int &car, int &k )
{
        
    int i;
    for ( i = 0; i < TS.trackCount; i++ )
    {
     
	    if ( ! QueueEmpty( TS.pTracks[ i ] ) )
        {
                                             
		    int headCar;    //车厢编号
	        headCar = GetHead( TS.pTracks[ i ] );
	        if ( headCar == car )
            {
     
		        DeQueue( TS.pTracks[ i ], headCar );
		        k = i; //将缓冲轨中车厢car从k号轨移出			
			    return true;
		    }
 	    }
    }
    return false;
}

#endif

  完整是程序包含对n节车厢进行重排的RealignCTrackStation函数及主函数等。
  车厢重排.cpp文档如下:

#include 
using namespace std;

typedef int QElemType;
#include "Realign.h"
//利用k个缓冲轨,对n节车厢重排
bool RealignCTrackStation( CTrackStation &TS, int *A, int &n )
{
     
    int k, nowOut = 1, i = 0;
    while ( nowOut <= n ) 
    {
     
        if ( HoldOut(TS, nowOut, k ) )
        {
     	
            cout << nowOut << " 号车厢从 "<< k << "号缓冲轨出队" << endl;
            nowOut++;
            continue;
        }
        if ( i >= n || ! HoldIn( TS, A[i], k ) ) 
            return false;
        cout << A[ i ] << " 号车厢进入 " << k << " 号缓冲轨" << endl;
        i++;
    }
    return true;
}

int main()
{
        
    int i, m, k;
    cout << "请输入需重排的车厢数:";
    cin >> m;
    int car, A[ m ];
    cout << "请依次输入需重排的车厢序列编号:";
    for ( i = 0; i < m; i++ )  
        cin >> A[i];	
    cout << "请输入缓冲轨(队列)的数目:";
    cin >> k;
    cout << endl;
    CTrackStation trackStation; //构建缓冲轨站
    bool ok = false;
    do
    {
       
        InitCTrackStation( trackStation, k );
        if ( RealignCTrackStation( trackStation, A, m ) ) 
        {
     //利用缓冲轨站重排车厢
            ok = true;
            cout << endl << "车厢已重排!" << endl;
        } 
        else 
        {
     
            DestroyCTrackStation( trackStation );
            cout << "缓冲轨的数目为"<< k <<"时,因车厢无法重排,请重输缓冲轨的数目:";
            cin >> k;
            cout << endl;
        }	
    }while ( ! ok );	
    DestroyCTrackStation( trackStation );	
   	
    return 0;
}

程序流程图

杭电数据结构课程实践-车厢调度_第1张图片

测试数据

杭电数据结构课程实践-车厢调度_第2张图片

你可能感兴趣的:(杭电数据结构课程设计)