2

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.
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Chase
  • 61
  • 6
  • Please show the current initialization and usage of the maxHeap – Gilad Green Jul 04 '17 at 17:26
  • Store your objects in `HashMap` in addition to `PriorityQueue` – talex Jul 04 '17 at 17:30
  • @GiladGreen Added – Chase Jul 04 '17 at 17:38
  • What you are looking for sounds a bit like an addressable priority queue, but unfortunately I wasn't able to find any useful implementations online. It has the following property: When inserting an element, you get a handle on this element which can be used for a `decreaseKey` or a `delete` operation. If you're interested, I can look for an old implementation of mine based on binary heaps. – Tobias Ribizel Jul 04 '17 at 18:35
  • Hey Tobias, I think Gilad's answer will work for me, but if you want to add it for future readers it will likely be useful! – Chase Jul 04 '17 at 18:39

1 Answers1

3

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.
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • Hashmaps are new to me and I'll need to do some digging for implementation, but do I have this concept correct? A hashmap can be searched, inserted, and deleted from in less than O(n) time, so with every change to a Task object, I can find its new index in the queue and change this information in the Hashmap. Then, if I ever need to find an ID, I just ask the Hashmap for the index of that ID. Do I have the idea right? – Chase Jul 04 '17 at 17:43
  • @Chase. Close. A hash map gives you insert, delete and search by the key all in `O(1)`. So by mapping between an id to the corresponding object in the max heap you can retrieve those tasks in `O(1)`. If you know the id you are looking for then there is no need to look by priority - just hashmap. If what you need is operations by priority - then the max heap. Maintain the two together and youll get both – Gilad Green Jul 04 '17 at 17:47