1. 程式人生 > >資料結構--用堆實現優先佇列

資料結構--用堆實現優先佇列

一、優先佇列實現方法

應想到使用二叉查詢樹實現優先佇列(線性表的思想被否決了,接下來該想到的也應該是樹結構了吧),​它可以使這兩種操作的平均執行時間都是O(logN)。但是使用二叉查詢樹會存在兩個問題

1:根節點的選擇。

2:使用指標的必要性。(我們不需要那麼“精確”的排序)

所以我們使用一種名為“二叉堆”的工具,它具有二叉查詢樹的部分思想,但我們將用陣列去實現它(你也可以認為就是用陣列實現了個二叉查詢樹

二、實現heap類
public class Heap<E extends Comparable<E>> {
    private ArrayList<E> list = new ArrayList<>();

    public Heap(){}
    public Heap(E[] objects){
        for (E object:objects) {
            add(object);
        }
    }

    public void add(E newObject){
        list.add(newObject);
        int currentIndex = list.size()-1;

        while (currentIndex>0){
            int parentIndex = (currentIndex-1)/2;
            if(list.get(currentIndex).compareTo(list.get(parentIndex)) > 0){
                E temp = list.get(currentIndex);
                list.set(currentIndex, list.get(parentIndex));
                list.set(parentIndex, temp);
            }
            else
                break;
            currentIndex = parentIndex;
        }
    }

    public E remove(){
        if(list.size() == 0) return null;

        E removedObject = list.get(0);
        list.set(0, list.get(list.size()-1));
        list.remove(list.size()-1);

        int currentIndex = 0;
        while (currentIndex<list.size()){
            int rightChildIndex = currentIndex*2+2;
            int leftChildIndex = currentIndex*2+1;
            if (leftChildIndex >= list.size()) break;

            int maxIndex = leftChildIndex;
            if(rightChildIndex < list.size()){
                if(list.get(maxIndex).compareTo(list.get(rightChildIndex)) < 0){
                    maxIndex = rightChildIndex;
                }
            }
            if(list.get(currentIndex).compareTo(list.get(maxIndex)) < 0){
                E temp = list.get(maxIndex);
                list.set(maxIndex, list.get(currentIndex));
                list.set(currentIndex, temp);
                currentIndex = maxIndex;
            }
            else break;
        }
        return removedObject;
    }

    public int getSize(){
        return list.size();
    }
}

二、實現PriorityQueue類

public class MyPriorityQueue<E extends Comparable<E>> {
    private Heap<E> heap = new Heap<>();

    public void enqueue(E newObject){
        heap.add(newObject);
    }
    public E dequeue(){
       return heap.remove();
    }
    public int getSize() {
        return heap.getSize();
    }
}

三、實現測試類

public class TestPriorityQueue {
    public static void main(String[] args){
        Patient p1 = new Patient("Tom", 1);
        Patient p2 = new Patient("Jack", 8);
        Patient p3 = new Patient("Smith", 3);
        Patient p4 = new Patient("John", 5);

        MyPriorityQueue priorityQueue = new MyPriorityQueue();
        priorityQueue.enqueue(p1);
        priorityQueue.enqueue(p2);
        priorityQueue.enqueue(p3);
        priorityQueue.enqueue(p4);
        while (priorityQueue.getSize() > 0){
            System.out.println(priorityQueue.dequeue());
        }
    }
    static class Patient implements Comparable<Patient>{
        private String name;
        private int priority;

        public Patient(String name, int priority){
            this.name = name;
            this.priority = priority;
        }

        @Override
        public int compareTo(Patient o) {
            return o.priority - this.priority;
        }

        @Override
        public String toString() {
            return "Patient{" +
                    "name='" + name + '\'' +
                    ", priority=" + priority +
                    '}';
        }
    }
}

四、總結

       父結點:(i-1)/2

       左子節點:2 * i +1

       右子節點:2 * i +2

       實現Comparable<E>介面再重寫compareTo方法可以自定義比較器

 static class Patient implements Comparable<Patient>
@Override
        public int compareTo(Patient o) {
            return o.priority - this.priority;
        }