Structure de données pour le Mécanisme d'ascenseur


Cette question m'a été posée lors d'un entretien d'entreprise - Quelle structure de données est efficace pour mettre en œuvre un mécanisme d'ascenseur?

Je ne suis pas en mesure de trouver la structure de données efficace pour cela même après beaucoup de recherche sur Google.

Je peux penser à la file d'attente prioritaire à implémenter it.Is file d'attente prioritaire une structure de données efficace ou une structure de données plus efficace existe-t-elle pour mettre en œuvre un mécanisme d'ascenseur?

Merci!

Author: Saurav Sahu, 2012-08-17

6 answers

Puisque vous ne pouvez pas implémenter mécanismes dans le logiciel (bien que vous puissiez certainement les modéliser ), je suppose que la question a porté sur le Algorithme d'ascenseur.

L'algorithme semble trompeusement simple, mais il est étonnamment très difficile à implémenter, même avec un bon ensemble de structures de données en main. Une bonne structure à utiliser pour cet algorithme est trois files d'attente prioritaires:

  1. Pour la direction actuelle avec des entrées au-delà du courant point,
  2. Pour la direction opposée, et
  3. pour la direction actuelle avant le point actuel.

Votre implémentation déciderait d'abord de la direction, puis choisirait une file d'attente dans laquelle placer la paire de valeurs {from, to} demandée.

 23
Author: dasblinkenlight, 2015-10-16 13:56:06

Et si nous utilisions deux listes chaînées, une pour les demandes de mouvement vers le haut et une autre pour les demandes de mouvement vers le bas.

Par exemple

Première demande: un).alors que l'ascenseur est au 0ème étage et une demande vient pour le 3ème étage.

Liste chaînée pour le mouvement vers le haut.

3->valeur null.

Liste chaînée pour le mouvement vers le bas.

Null.

Deuxième requête: b). alors que l'ascenseur a déménagé au 1er étage et une demande vient du 2ème plancher pour le mouvement vers le haut.

Liste chaînée pour le mouvement vers le haut.

2->3->null

Liste chaînée pour le mouvement vers le bas.

Null.

Troisième demande: c) Supposons que 2 personnes entrent au 2ème étage, l'une appuie sur un bouton pour le 5ème étage et l'autre pour le 1er.

Liste chaînée pour le mouvement vers le haut.

3->5->null

Remarque: Ici 2 a été supprimé de la liste chaînée vers le haut comme il a été atteint.

Liste chaînée pour le mouvement vers le bas.

1->null.

D)Supposons qu'une personne entre au 3ème étage et appuie sur le bouton pour le 0ème étage

Liste chaînée pour le mouvement vers le haut.

5 - >null

Liste chaînée pour le mouvement vers le bas.

1->0->la valeur null.

Une fois que 5th floor iis atteint la liste chaînée des demandes ascendantes devient vide, de sorte que la liste chaînée vers le bas peut être considérée pour le mouvement.

Si les deux la liste chaînée sont vides alors l'ascenseur serait au repos.

Donc je pense que la liste liée peut également être une structure de données efficace pour l'ascenseur

 12
Author: sacrishi, 2015-07-01 17:13:33

Ci-dessous est une façon de concevoir le système d'ascenseur. Chaque ascenseur utilise la file d'attente (il peut s'agir d'une file d'attente bloquante) pour stocker les demandes d'étage. Il existe également un ElevatorManager central qui surveille toutes les files d'attente d'ascenseur et peut déléguer des demandes à un certain ascenseur en fonction de certaines règles métier. C'est le travail d'ElevatorManager de déléguer efficacement les demandes à l'ascenseur concerné. Ci dessous pseudocode n'optimise pas l'algorithme de délégation mais il montre comment la délégation réelle pourrait être faite à un liste des ascenseurs.

Classes nécessaires pour le système d'ascenseur:

ElevatorManager [Singleton - C'est l'ascenseur principal programme qui va gérer n ascenseurs dans le bâtiment]
Membres:
Liste des ascenseurs
File d'attente d'étage.Request / / Ceci maintient la demande pour les deux directions. Une amélioration pourrait être de garder deux files d'attente, une pour chaque direction, mais cela augmenterait la complexité
MIN_FLOOR
MAX_FLOOR
Opérations:
delgate ()
halt() // mettre l'ensemble du système d'ascenseur en mode maintenance ou en mode arrêt


Ascenseur [Représente les ascenseurs individuels. Il pourrait être n ascenseurs dans un immeuble]
Membres:
File d'attente de Floor / / cela doit être trié donc peut être une PriorityQueue pourrait être utilisée
Direction : Enum [Enum de direction - haut, le bas, d'attente, de repos, maintenance]
CurrentFloor : Étage
Opérations:
fonctionner()
moveUP ()
moveDown()
openDoor()
closeDoor()
callEmergencyLine ()
getDirection ()
getCurrentFloor ()
setInMaintenanceMode()


Plancher [Représente étages]
Membres:
Énumération des étages
Demande de classe {
currentFloor
destinationFloor
Direction [Haut, bas]
}
Opération:
Groupe ()
goDown()

Quelques-uns des principaux pseudo-code ci-dessus:

class Floor {
    goUp() {
        ElevatorManager.queue.offer(new Request(currentFloor, destinationFloor, up));
    }   

    goDown() {
        ElevatorManager.queue.offer(new Request(currentFloor, destinationFloor, down));
    }
}

ElevatorManager {
    delegate() {

        // Instead of using one object, we could use a list to track idle and elevators moving in same direction so that these list could be used for next requests in queue
        // but again to simplify pseudocode, I am using single objects instead of lists
        Elevator idleElevator; // track idle elevator
        Elevator elevatorMovingInSameDirection; // elevator moving in same direction as next request in main elevator manager queue 

        while(!halt()) { //keep delegating until powered down or whole system is halted through main controls

            if(queue.peek() != null) {

                Request req = queue.peek();
                boolean startAgain = false; // flag to start from beginning if the request is already pushed to one of the elevators queue during iterating elevators

                for(Elevator elevator : elevators) {

                    // first find if there is an elevator at current floor going in same direction as current request in queue
                    if(req.currentFloor == elevator.currentFloor && req.direction == elevator.direction) {
                        elevator.queue.offer(req.destinationFloor);
                        queue.poll(); // remove this request from Elevator Manager queue

                        startAgain = true;
                        break;
                    }

                    // check if this elevator is idle
                    if(elevator.direction == "idle")) {
                        idleElevator = elevator; // For this simple design, I am ok to overwrite idle elevator value and instead get the latest idle elevatior
                    }

                    // check if this elevator is moving in desired direction and elevator's current floor is behind desired floor in queue
                    if(elevator.direction == req.direction) {

                        // Make sure elevators moving in same direction should also be behind the floor where request is made
                        if(req.direction == "Up" && req.currentFloor - elevator.currentFloor > 0) {

                            elevatorMovingInSameDirection = elevator; // Same as above, it's ok to get this overwritten and instead get the latest elevator moving in same      direction
                        }

                        // Make sure elevators moving in same direction should also be behind the floor where request is made
                        if(req.direction == "Down" && req.currentFloor - elevator.currentFloor < 0) {
                            elevatorMovingInSameDirection = elevator;
                        }
                    }

                }

                // Only delegate to other floors if you could not find elevator going in same direction at same floor from where the request was made
                if(!startAgain && idleElevator != null) {
                    idleElevator.queue.offer(req.destinationFloor);
                    queue.poll();
                }

                // if we could neither find elevator at current floor nor idle elevator then send this request to elevator behind current Floor and moving in same direction as the request
                if(!startAgain && elevatorMovingInSameDirection != null) {
                    elevatorMovingInSameDirection.queue.offer(req.destinationFloor);
                    queue.poll();
                }


            }
        }
    }
}


Elevator {

    moveUp() {
        this.currentFloor += 1;
    }

    moveDown() {
        this.currentFloor -= 1;
    }

    operate() {

        while(queue.peek() != null) {

            Floor nextFloorInQueue = queue.peek();

            while(this.currentFloor != nextFloorInQueue.request.destinationFloor) {
                if(this.direction == "Up") {
                    moveUp();
                } else if(this.direction == "down") {
                    moveDown();
                }
            }

            queue.poll(); // remove the request from queue
            open(); //open door

            Direction backUpDirection = this.direction; //back up elevators direction to retrieve it later once dooor closes
            this.direction = "idle"; // set state to idle to let elevatorManager know that requests at current floor could be offered to this elevator queue

            Thread.sleep(10000); // sleep for 10 seconds so that people can leave elevator

            close(); // once people are out close door to move to next floor in queue
            this.direction = backUpDirection;
        }

        this.direction = "idle"; // once queue is empty set the direction to idle
    }
}

Il est également disponible ici sur mon Github: https://github.com/prabhash1785/Java/blob/master/ObjectOrientedDesign/src/com/prabhash/java/design/objectoriented/elevator/ElevatorDesignWithPseudocode.md

 2
Author: Prabhash Rathore, 2016-02-12 23:19:58

entrez la description de l'image ici

Chaque pression sur un bouton entraîne une demande d'ascenseur qui doit être servie. Chacune de ces demandes est suivie à un endroit mondial. ElevatorRequests - la classe qui stocke les demandes d'ascenseur peut utiliser différentes stratégies pour planifier les demandes d'ascenseur. L'ascenseur est commandé par une classe de contrôleur que nous appelons ElevatorController . Le contrôleur d'ascenseur indique à l'ascenseur ce qu'il faut faire et peut également arrêter / démarrer l'ascenseur du bâtiment. Le contrôleur d'ascenseur lit la prochaine demande d'ascenseur à traiter et la sert.

Button est une classe abstraite définissant un comportement commun comme illuminate, doNotIlluminate. FloorButton, ElevatorButton étendre le type de bouton et définir placeRequest () qui est appelé lorsque le bouton est enfoncé. Les deux presses de bouton de plancher et la presse de bouton d'ascenseur ajoute des demandes à un endroit commun.

ElevatorController exécute le show en lisant la prochaine requête à traiter et en instruisant l'ascenseur de quoi faire.

 1
Author: Ishan Aggarwal, 2017-09-24 18:23:52

Que diriez-vous d'avoir un tableau, où chaque entrée de tableau représente un étage. Lorsque l'utilisateur voulait s'arrêter à un étage, il marquera cette entrée dans le tableau, et l'ascenseur regardera dans le tableau et effacera l'entrée s'il marque lorsque l'ascenseur atteint cet étage. Similaire à l'algorithme de planification SCAN/CSAN. J'attends avec impatience vos commentaires

 0
Author: rgaut, 2014-09-26 22:58:20

Pour simplifier, considérons un système d'ascenseur unique .

Structure de Données utilisée: Simple listes pour stocker sol#, enum pour de l'événement et de l'état.

Le système peut être piloté par Event-State. Chaque aspect du comportement ou de l'environnement des utilisateurs doit être pris en compte pour décider quels scénarios peuvent être jetés à l'ascenseur.

Events of the elevator : GOINGUP, GOINGDOWN, STOP 
States of the elevator : ONMOVE, WAITING (between door open and close), IDLE (serving no one), UNDERMAINTENANCE

Elevator movement is usually driven by two activites:
1. Press Up or Down key (before the entry gate of elevator) and wait for the elevator to come and serve you. (Press-And-Wait, say PAW) 
2. Enter inside the elevator and make request by pressing keys (Enter-And-Request, say EAR)

So it can said that PAW from outside and EAR from inside can decide the hops of the elevator. But what about direction?

Two possible types of PAW: PAWup (press Up button) and PAWdown (press Down button)

Now, EAR can be any of the three types depending upon the users behavior. These are the critical challenges in deciding the algorithm: 
1.) Normal - same direction as PAW (wanted to go down and enter lower floor#) 
2.) Opposite - wanted to go down BUT enter higher floor#
3.) Indecisive - Do Nothing, no key press

Now comes all the important rules:
RULE 1: If at IDLE, use FCFS to decide between the DownList front and UpList front - whoever is oldest, serve it first to ensure less waiting time. 
RULE 2: When both lists (DownList and UpList) are empty, move elevator to IDLE state. 
RULE 3: Elevator state change GOINGUP->STOP clears that floor# from UpList. Similarly, GOINGDOWN->STOP clears that floor from DownList.
RULE 4: Absolute Zero Skipping: GOINGxxx serves as many floors in xxxList as possible. 
RULE 5: Elevator doesn't favour Opposite-EAR, and obviously can't serve Indecisive-EAR.
RULE 6: Elevator in UNDERMAINTENANCE state is shunned from all external signals.
RULE 7: In the event of Power-cuts or Fire, the elevator goes and stops at Lobby. Flooding??

To achieve RULE#5, GOINGDOWN clears all the lower floor# in DownList in ONE GO. Similarly, GOINGUP clears all the higher floor# in UpList.    

Lets discuss one scenario to clear the above concepts:
Say, an elevator is resting at floor 7 is at IDLE state, 
    DownList : 
    UpList : 

IDLE@7 - PAWdown@12 then PAWup@9 then PAWdown@13
    DownList : 12, 13 (older requests at lower index.Push new requests at front.)
    UpList : 9 
    Using RULE#2, in the above case, 
    Event: GOINGUP to Pick@12.  

WAITING@12  - 12 cleared following RULE#3

MeanWhile, PAWup@8 then PAWup@10 then PAWdown@10, so updated lists are:
    DownList : 13, 10 
    UpList : 9, 8, 10

So here, in the current situation, if the EAR is
1.) Normal, GOINGDOWN(towards new EAR) is triggered.
2.) Opposite/Indecisive, GOINGDOWN(towards 9) is triggered and add the new EAR in UpList. 

En utilisant les règles mentionnées ci-dessus, l'ascenseur continue son travail habituel.

 0
Author: Saurav Sahu, 2016-09-16 13:27:52