火車車廂重排問題--隊列模擬


①問題描述

一列貨運列車共有n節車廂,每節車廂將停放在不同的車站。假定n個車站的編號分別為1n,即貨運列車按照第n站至第1站的次序經過這些車站。為了便於從列車上卸掉相應的車廂,車廂的編號應與車站的編號相同,這樣,在每個車站只要卸掉最后一節車廂。所以,給定任意次序的車廂,必須重新排列它們。

車廂的重排工作可以通過轉軌站完成。在轉軌站中有一個入軌、一個出軌和k個緩沖軌,緩沖軌位於入軌和出軌之間。假定緩沖軌按先進先出的方式運作,設計算法解決火車車廂重排問題。

②基本要求

  • 設計存儲結構表示n個車廂、k個緩沖軌以及入軌和出軌;

  • 設計並實現車廂重排算法;

  • 分析算法的時間性能。

③設計思想

假設有3個緩沖軌,入軌中有9節車廂,次序為5,8,1,7,4,2,9,6,3,重排后,9節車廂出軌次序為9,8,7,6,5,4,3,2,1。重排過程如下:

3號車廂不能直接移至出軌(因為1號車廂和2號車廂必須排在3號車廂之前),因此,把3號車廂移至H16號車廂可放在H13號車廂之后(因為6號車廂將在3號車廂之后出軌)。9號車廂可以繼續放在H16號車廂之后,而接下來的2號車廂不能放在9號車廂之后(因為2號車廂必須在9號車廂之前出軌)。因此,應把2號車廂移至H24號車廂可以放在H22號車廂之后,7號車廂可以繼續放在4號車廂之后,如圖4所示。至此,1號車廂可通過H3直接移至出軌,如圖5所示。由於5號車廂此時仍在入軌中,所以把8號車廂移動至H2,這樣就可以把5號車廂直接從入軌移至出軌,如圖6所示。此后,可依次從緩沖軌中移出6號、7號、8號和9號車廂,如圖7所示。

 

4 369247依次入緩沖軌

 

5 1移至出軌,234移至出軌

 

6 8入緩沖軌,5移至出軌

 

7 6789移至出軌

由上述重排過程可知:在把車廂c移至緩沖軌時,車廂c應移動到這樣的緩沖軌中:該緩沖軌中隊尾車廂的編號小於c;如果有多個緩沖軌滿足這一條件,則選擇隊尾車廂編號最大的緩沖軌;否則選擇一個空的緩沖軌。

⑤思考

  • 如果緩沖軌按后進先出的方式工作,即用棧表示緩沖軌,應如何解決火車車廂重排問題?

 

 

 

#include<iostream>
using namespace std;
class Queue
{
public:
    struct Node
    {
        int data;
        Node * next;
        Node():next(NULL) {}
        Node(int a):data(a),next(NULL) {}
    };
    Node * Front;
    Node * rear;
    int length;
    Queue()
    {
        Node * p = new Node();
        Front = p;
        rear = p;
        length = 0;
    }
    int inQueue(int a)
    {
        Node * p = new Node(a);
        rear -> next = p;
        rear = rear -> next;
        length ++;
    }
    int showrear()
    {
        return rear->data;
    }
    int showfront()
    {
        return Front->next->data;
    }
    void outQueue()
    {

        Node * p = Front -> next;
        Front -> next = p -> next;
        delete p;
        length--;
    }
    void printf()
    {
        Node * p = Front -> next;
        for(int i = 0 ; i < length ; i++)
        {
            cout<<p->data<<" ";
            p = p -> next;
        }
    }
    bool isEmpty()
    {
        return length == 0;
    }

};
int main()
{
    int n , k ;//n代表車廂數,k代表軌道
    int nowOut = 1;//要輸出的車廂編號
    cout<<"input n:"<<endl;
    cout<<"input k:"<<endl;
    cout<<"input train"<<endl;
    cin>>n>>k;
    Queue dusk[k+2];//0到k-1代表緩沖軌道,k代表入軌,k+1代表出軌
    for(int i = 0 ; i < n ; i++)//輸入入隊車廂號
    {
        int a ;
        cin>>a;
        dusk[k].inQueue(a);
    }
    while(!dusk[k].isEmpty())//出軌不為空的時候循環
    {
        int flag = 0;//判斷進入新的緩沖軌還是進入非空緩沖軌道。
        //0進入新的緩沖軌道,非0進入非空緩沖軌道
        int z = 0;//判斷是否能直接出軌。0為不能直接出軌,非0為可出軌。
        int flag_end = 0;//退出循環判定
        if(dusk[k].showfront()==nowOut)//如果出軌隊頭車廂號等於現在要出軌的車廂號
        {
            for(int i = 0 ; i < k ; i++)//遍歷所有循環軌,找出一個空的
            {
                if(dusk[i].isEmpty())//找到空的循環軌,輸出
                {

                    cout<<dusk[k].showfront()<<" train by trace "<<i+1<<" out."<<endl;
                    dusk[k+1].inQueue(dusk[k].showfront());
                    nowOut++;
                    dusk[k].outQueue();
                    z++;
                    flag++;
                    break;
                }
            }
        }
        if(z==0)//如果不能直接出軌,找到比當前要出軌的車廂小的非空軌道,並入軌
        {
            for(int i = 0 ; i < k ; i++)
            {
                if(!dusk[i].isEmpty()&&(dusk[i].showrear()<dusk[k].showfront()))
                {
                    cout<<dusk[k].showfront()<<" train in "<<i+1<<" trace."<<endl;
                    dusk[i].inQueue(dusk[k].showfront());
                    dusk[k].outQueue();
                    flag ++;
                    break;
                }
            }
        }
        //如果找不到比當前要出軌的車廂小的非空軌道,就找空的緩沖軌,並入軌
        if(flag == 0)
        {
            for(int i = 0 ; i < k ; i++)
            {
                if(dusk[i].isEmpty())
                {
                    cout<<dusk[k].showfront()<<" train in "<<i+1<<" trace."<<endl;
                    dusk[i].inQueue(dusk[k].showfront());
                    dusk[k].outQueue();
                    break;
                }
                if(i==k-1)//如果找不到新的緩沖軌,那么輸出ERROR,結束循環
                {
                    cout<<"ERROR!"<<endl;
                    flag_end = 1;//結束循環的標志
                    break;
                }
            }
        }
        if(flag_end == 1)//退出while循環
        {
            break;
        }
        //遍歷所有非空軌道隊頭車廂號,如果等於要出隊的車廂號,就出軌並且重新循環
        for(int i = 0 ; i < k ; i++)
        {
            if(!dusk[i].isEmpty()&&dusk[i].showfront()==nowOut)
            {
                cout<<dusk[i].showfront()<<" train by trace "<<i+1<<" out."<<endl;
                dusk[k+1].inQueue(dusk[i].showfront());
                dusk[i].outQueue();
                nowOut++;
                i = -1;
            }
        }
    }

    dusk[k+1].printf();//打印出軌車廂順序
}

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM