Search code examples
javaalgorithmdata-structurespriority-queuemax-heap

Improving Key Search Time Complexity in a Priority Queue Heap


I have a custom Task class which contains a priority value as well as some additional fields, shown below:

class Task{

    int ID;
    int Priority;
    int Time;

    public Task(int i, int p, int t){
        this.ID = i;
        this.Priority = p;
        this.Time = t;
    }

    //Getters, etc
}

These are stored in a max heap by priority, which works fine. However, if I want to find a Task object with a specific ID value, that has to be done in O(n) time due to the linear search (using a basic array of Tasks as a heap):

public int getTimeOfID(int ID){            

    for(int i = 1; i < heapSize+1; i++){
        if (heap[i].getTaskID() == taskID){
            return heap[i].getTimeLeft();
        }
    }

    return -1;
}

I've come across several references to a "modified heap" that could be used to improve ID search to O(1) time, but haven't found a concrete implementation example. Is this possible to do, and if so, how would I do it? A Java or pseudcode example would be greatly appreciated, but even just the name of a relevant data structure to begin my search would be helpful. Thanks for any assistance.

EDIT: Additional code added as requested:

//initial variables

private Task[] heap;
private int heapSize, capacity;
int maxTasksHigh;

//Constructor

public PQ(int maxTasks){        
    this.capacity = maxTasks+1;
    heap = new Task[this.capacity];
    heapSize = 0;
    maxTasksHigh = maxTasks;
}

//Addition

public void add(int ID, int time){        
    Task newTask = new Task(ID, time);
    heapSize++;
    heap[heapSize] = newTask;
    int target = heapSize;

    heap[target] = newTask;
    reorder(target);
}

//etc.

Solution

  • What you can do is add a HashMap to map between an ID and the Task object in the Max Heap.

    Then when adding or removing an item you add or remove it from the HashMap<String, Task>. These operations will take O(1) so will not harm the time complexity of the Max Heap. By using the HashMap in addition to the Max Heap you can check if a given ID exists and retrieve its item in O(1).

    A word of caution: If you return the reference to the object in the Max Heap through these extra methods an outsider can change the value of the item and therefore break the Max Heap. Solve it by returning a deep clone of the object or by having your Task immutable.


    Update after adding code:

    • Create a new member of the class of HashMap<String, Task> and initialize it in the constructor.
    • In the add method check if a.containsKey() for the given Task. If not add it to the Max Heap and to the HashMap.
    • Update logic of other methods as needed.