实现电梯优先队列

时间:2013-04-30 16:44:25

标签: java algorithm

我有以下代码来实现Elevator:

public class Elevator{

   Direction dir;
   int floorNum;
   int capacity;

   public void moveUp{
      dir = Direction.Up;
   }

   public void moveDown{
     dir = Direction.Down
   }

   public boolean isMoving{
     returns dir.equals(Direction.STATIONARY);
   }
}


public class ElevatorController{

   Elevator[] elevators;

   PriorityQueue<Integer> queue = new PriorityQueue<Integer>;

   public void buttonPressed{Direction d, int fromFloot, int toFloor){ 


   }
}

我读到一个实现电梯的好方法是实现一个优先级队列来获得电梯,但我不确定如何。

队列将包含目标楼层。

你会如何推荐实施它?

2 个答案:

答案 0 :(得分:6)

一种可能性是使用两个单独的TreeSet来排序楼层updown。如果您要在currentFloor之上添加一个楼层,请将其添加到up,如果您在currentFloor下面添加一个楼层,则将其添加到down;如果您添加等于currentFloor的楼层,则将其丢弃。 TreeSet会自动丢弃重复项。在确定要访问的下一个楼层时,如果direction == UP,则访问up中的下一个最低楼层,如果direction == DOWN,则访问down中的下一个楼层。

或者你可以使用一个TreeSet并试图想出一个聪明的比较器,它将电梯方向考虑在内,但这似乎比它的价值更麻烦。

private TreeSet<Integer> up = new TreeSet<>(); // floors above currentFloor
private TreeSet<Integer> down = new TreeSet<>(); // floors below currentFloor
private int currentFloor = 0;
private Enum direction = direction.UP;

public void addFloor(int f) {
    if(f < currentFloor) {
        down.add(f);
    } else if(f > currentFloor) {
        up.add(f);
    }
    // else f == currentFloor, so don't add the floor to either queue
}

public int nextFloor() {
    if(direction == direction.DOWN) {
        return down.pollLast(); // highest floor in down, or null if empty
    } else {
        return up.pollFirst(); // lowest floor in up, or null if empty
    }
}

答案 1 :(得分:2)

我尝试使用单个TreeSet实现Elevator。

这是一个完整的解决方案:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;

public class MyLift {

    public static void main(String[] args) {
        System.out.println("Welcome to MyLift");
        // RequestListenerThread to read requested floor and add to Set
        Thread requestListenerThread = new Thread(new RequestListener(),
                "RequestListenerThread");
        // RequestProcessorThread to read Set and process requested floor
        Thread requestProcessorThread = new Thread(new RequestProcessor(),
                "RequestProcessorThread");
        requestListenerThread.start();
        requestProcessorThread.start();
    }
}

class Elevator {
    private static Elevator elevator = null;
    private static TreeSet<Integer> requestSet = new TreeSet<Integer>();
    private int currentFloor = 0;

    private Direction direction = Direction.UP;

    private Elevator() {
    };

    /**
     * @return singleton instance
     */
    static Elevator getInstance() {
        if (elevator == null) {
            elevator = new Elevator();
        }
        return elevator;
    }

    /**
     * Add request to Set
     * 
     * @param floor
     */
    public synchronized void addFloor(int f) {
        requestSet.add(f);
        // Notify the thread that a new request has come.
        notify();
    }

    /**
     * @return next request to process based on elevator current floor and
     *         direction
     */
    public synchronized int nextFloor() {

        Integer floor = null;

        if (direction == Direction.UP) {
            if (requestSet.ceiling(currentFloor) != null) {
                floor = requestSet.ceiling(currentFloor);
            } else {
                floor = requestSet.floor(currentFloor);
            }
        } else {
            if (requestSet.floor(currentFloor) != null) {
                floor = requestSet.floor(currentFloor);
            } else {
                floor = requestSet.ceiling(currentFloor);
            }
        }
        if (floor == null) {
            try {
                System.out.println("No Request to process. Waiting");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("Processing Request : " + floor);
            requestSet.remove(floor);
        }
        return (floor == null) ? -1 : floor;
    }

    public int getCurrentFloor() {
        return currentFloor;
    }

    /**
     * Set current floor and direction based on requested floor
     * 
     * @param currentFloor
     */
    public void setCurrentFloor(int currentFloor) {
        if (this.currentFloor > currentFloor) {
            setDirection(Direction.DOWN);
        } else {
            setDirection(Direction.UP);
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.currentFloor = currentFloor;
        System.out.println("Floor : " + currentFloor);
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

}

class RequestProcessor implements Runnable {

    @Override
    public void run() {
        while (true) {
            Elevator elevator = Elevator.getInstance();
            int floor = elevator.nextFloor();
            int currentFloor = elevator.getCurrentFloor();
            if (floor >= 0) {
                if (currentFloor > floor) {
                    while (currentFloor > floor) {
                        elevator.setCurrentFloor(--currentFloor);
                    }
                } else {
                    while (currentFloor < floor) {
                        elevator.setCurrentFloor(++currentFloor);
                    }
                }
            }
        }
    }
}

class RequestListener implements Runnable {

    @Override
    public void run() {

        while (true) {
            String floorNumberStr = null;
            try {
                // Read input from console
                BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(System.in));
                floorNumberStr = bufferedReader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (isValidFloorNumber(floorNumberStr)) {
                System.out.println("User Pressed : " + floorNumberStr);
                Elevator elevator = Elevator.getInstance();
                elevator.addFloor(Integer.parseInt(floorNumberStr));
            } else {
                System.out.println("Floor Request Invalid : " + floorNumberStr);
            }
        }
    }

    /**
     * This method is used to define maximum floors this elevator can process.
     * @param s - requested floor
     * @return true if requested floor is integer and upto two digits. (max floor = 99)
     */
    public boolean isValidFloorNumber(String s) {
        return (s != null) && s.matches("\\d{1,2}");
    }

}

enum Direction {
    UP, DOWN
}