"git@gitlab.caltech.edu:cs24-19fa/git_rec_nano.git" did not exist on "3a5eaeb40193992148c4da1cd82d77a16784c82f"
MinFourHeap.java 5.16 KB
package edu.caltech.cs2.datastructures;

import edu.caltech.cs2.interfaces.IDictionary;
import edu.caltech.cs2.interfaces.IPriorityQueue;

import java.util.Iterator;

public class MinFourHeap<E> implements IPriorityQueue<E> {

    private static final int DEFAULT_CAPACITY = 10;
    private static final int GROWTH_FACTOR = 2;
    private int size;
    private PQElement<E>[] data;
    private IDictionary<E, Integer> keyToIndexMap;

    /**
     * Creates a new empty heap with DEFAULT_CAPACITY.
     */
    public MinFourHeap() {
        this.size = 0;
        this.data = new PQElement[DEFAULT_CAPACITY];
        this.keyToIndexMap = new ChainingHashDictionary<>(MoveToFrontDictionary::new);
    }

    @Override
    public void increaseKey(PQElement<E> key) {
        if (!this.keyToIndexMap.containsKey(key.data)) {
            throw new IllegalArgumentException("Can't modify a nonexistent element!");
        }
        if (key.priority > this.data[this.keyToIndexMap.get(key.data)].priority) {
            this.data[this.keyToIndexMap.get(key.data)] = key;
            percDown(this.keyToIndexMap.get(key.data));
        }
    }

    @Override
    public void decreaseKey(PQElement<E> key) {
        if (!this.keyToIndexMap.containsKey(key.data)) {
            throw new IllegalArgumentException("Can't modify a nonexistent element!");
        }
        else if (key.priority < this.data[this.keyToIndexMap.get(key.data)].priority) {
            this.data[this.keyToIndexMap.get(key.data)] = key;
            percUp(this.keyToIndexMap.get(key.data));
        }
    }

    @Override
    public boolean enqueue(PQElement<E> epqElement) {
        if (this.keyToIndexMap.containsKey(epqElement.data)) {
            throw new IllegalArgumentException("This key is already in MinFourHeap!");
        }
        else if (this.size >= this.data.length) {
            PQElement<E>[] temp = new PQElement[this.size * GROWTH_FACTOR];
            System.arraycopy(this.data, 0, temp, 0, this.size);
            this.data = temp;
        }
        this.data[this.size] = epqElement;
        this.keyToIndexMap.put(epqElement.data, this.size);
        this.size++;
        percUp(this.size - 1);
        return true;
    }

    @Override
    public PQElement<E> dequeue() {
        if (this.size == 0) {
            return null;
        }
        else if (this.size == 1) {
            PQElement<E> root = this.data[0];
            this.size--;
            this.keyToIndexMap.remove(root.data);
            this.data[0] = null;
            return root;
        }
        PQElement<E> root = this.data[0];
        this.size--;
        this.keyToIndexMap.remove(root.data);
        this.data[0] = this.data[this.size];
        this.keyToIndexMap.put(this.data[0].data, 0);
        percDown(0);
        return root;
    }

    @Override
    public PQElement<E> peek() {
        if (this.size == 0) {
            throw new IllegalArgumentException("Empty array, nothing to peek!");
        }
        return data[0];
    }

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public Iterator<PQElement<E>> iterator() {
        return null;
    }

    private boolean hasChild (int index, int childNum) {
        int childIndex = ((4 * index) + childNum);
        return (childIndex < this.size && childIndex > 0);
    }

    private void percUp(int idx) {
        while ((idx - 1) / 4 >= 0 && this.data[(idx - 1) / 4].priority > this.data[idx].priority) {
            int parentidx = (idx - 1) / 4;
            PQElement temp = data[parentidx];
            data[parentidx] = data[idx];
            data[idx] = temp;
            int temp2 = this.keyToIndexMap.get(data[parentidx].data);
            this.keyToIndexMap.put(data[parentidx].data, this.keyToIndexMap.get(data[idx].data));
            this.keyToIndexMap.put(data[idx].data, temp2);
            idx = (idx - 1) / 4;;
        }
    }

    private void percDown(int idx) {
        while (hasChild(idx, 1)) {
            int parentidx = 0;
            int minchildIndex = ((4 * idx) + 1);
            if (minchildIndex >= this.size) {
                minchildIndex = 1;
            }
            double min = this.data[minchildIndex].priority;
            int minChildIndex = minchildIndex;
            int childNum = 2;
            while (hasChild(idx, childNum) && childNum <= 4) {
                int childIndex = ((4 * idx) + childNum);
                if(this.data[childIndex].priority < min) {
                    min = this.data[childIndex].priority;
                    minChildIndex = childIndex;
                }
                childNum++;
            }
            parentidx = minChildIndex;
            PQElement smallestChild = this.data[parentidx];
            if (smallestChild.priority < this.data[idx].priority) {
                PQElement temp = data[parentidx];
                data[parentidx] = data[idx];
                data[idx] = temp;
                int temp2 = this.keyToIndexMap.get(data[parentidx].data);
                this.keyToIndexMap.put(data[parentidx].data, this.keyToIndexMap.get(data[idx].data));
                this.keyToIndexMap.put(data[idx].data, temp2);
            } else {
                break;
            }
            idx = parentidx;
        }
    }
}