DataStructure for Elevator Mechanism
What if we used two linked list one for upward direction movement requests and another for downward direction movement request.
e.g
First request: a).while lift is on 0th floor and a requests come for 3rd floor.
linked list for upward movement.
3->null.
linked list for downward movement.
null.
Second request: b). while lift has moved to 1st floor and a request comes from 2nd floor for upward movement.
linked list for upward movement.
2->3->null
linked list for downward movement.
null.
Third request: c) Suppose 2 persons enter on the 2nd floor, one presses button for 5th floor and another for 1st.
linked list for upward movement.
3->5->null
Note: Here 2 has been deleted from upward linked list as it has been reached.
linked list for downward movement.
1->null.
d)Suppose a person enters on 3rd floor and presses button for 0th floor
linked list for upward movement.
5->null
linked list for downward movement.
1->0->null.
Once 5th floor iis reached upward requests linked list becomes empty so downwards linked list can be considered for movement.
If both the linked list are empty then elevator would be at rest.
So i think linked list can also be an effective data structure for elevator
How about having an array, where each array entry represents a floor. When user wanted to stop to a floor he will mark that entry in the array, and elevator will look into array and clear the entry if it marks when elevator reaches to that floor. Similar to SCAN/CSAN scheduling algorithm. I look forward for your comments
Below is one way to design Elevator System. Each elevator uses Queue (it could be Blocking Queue) to store floor requests. Also there is a central ElevatorManager which monitors all Elevator queues and it can delegate requests to a certain elevator depending upon some business rules. It's the job of ElevatorManager to efficiently delegate requests to the relevant elevator. Below pseudocode does not optimize the delegation algorithm but it shows how actual delegation could be done to a list of elevators.
Classes needed for Elevator System:
ElevatorManager [Singleton - This is the main elevator program which will manage n elevators in the building]
Members:
List of Elevator
Queue of Floor.Request // This maintains request for both directions. One improvement could be to keep two queues, one for each direction but it would increase complexity
MIN_FLOOR
MAX_FLOOR
Operations:
delgate()
halt() // set whole elevator system in maintenance mode or halt operation
Elevator [Represents individual elevators. There could be n elevators in a building]
Members:
Queue of Floor // this needs to be sorted so may be a PriorityQueue could be used
Direction : Enum [Enum of direction - up, down, wait, idle, maintenance]
CurrentFloor : Floor
Operations:
operate()
moveUp()
moveDown()
openDoor()
closeDoor()
callEmergencyLine()
getDirection()
getCurrentFloor()
setInMaintenanceMode()
Floor [Represents individual floors]
Members:
eNum of Floors
class Request {
currentFloor
destinationFloor
Direction [Up, Down]
}
Operation:
goUp()
goDown()
Some of the main pseudocode for above components:
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
}
}
It's also availabe here on my Github: https://github.com/prabhash1785/Java/blob/master/ObjectOrientedDesign/src/com/prabhash/java/design/objectoriented/elevator/ElevatorDesignWithPseudocode.md
Since you cannot implement mechanisms in software (although you can certainly model them), I assume that the question has been about the Elevator algorithm.
The algorithm looks deceivingly simple, yet it is surprisingly very tough to implement, even with a good set of data structures in hand. A good structure to use for this algorithm is three priority queues:
- For the current direction with entries past the current point,
- For the opposite direction, and
- for the current direction prior to the current point.
Your implementation would first decide the direction, then pick a queue into which to place the requested pair of {from, to}
values.