資料結構-堆實現優先佇列(java)
阿新 • • 發佈:2019-01-22
佇列的特點是先進先出。通常都把佇列比喻成排隊買東西,大家都很守秩序,先排隊的人就先買東西。但是優先佇列有所不同,它不遵循先進先出的規則,而是根據佇列中元素的優先權,優先權最大的先被取出。這就很像堆的特徵:總是移除優先順序最高的根節點。
重點:優先順序佇列,是要看優先順序的,誰的優先順序更高,誰就先得到許可權。不分排隊的順序!
上篇文章解釋了堆的概念實現,現在用堆實現優先佇列:
MyPriorityQueue.java//最大堆 import java.util.ArrayList; public class Heap<E extends Comparable>{ private ArrayList<E> list=new ArrayList<E>();//用陣列實現堆 public Heap(){} public Heap(E[] objects){ for(int i=0;i<objects.length;i++){ add(objects[i]); } } 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 removeObject=list.get(0); list.set(0, list.get(list.size()-1));//把最後一個結點放在根結點的位置 list.remove(list.size()-1); int currentIndex=0; while(currentIndex<list.size()){ int leftChildIndex=2*currentIndex+1; int rightChildIndex=2*currentIndex+2;//左右孩子結點的座標 if(leftChildIndex>=list.size())break; //比較左右孩子的值,使maxIndex指向值大的結點 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 removeObject; } public int getSize(){ return list.size(); } }
TestMyPriorityQueueMainClass.javapublic class MyPriorityQueue<E extends Comparable> { private Heap<E> heap=new Heap<E>();//用堆實現優先佇列 //入佇列 public void enqueue(E e){ heap.add(e); //這個add以後,堆會自己調整成一個新堆 } //出佇列 public E dequeue(){ return heap.remove();//這移除出之後,堆會自己調整,還是一個新堆 } public int getSize(){ return heap.getSize(); } }
public class TestMyPriorityQueueMainClass { public static void main(String[] args) { // TODO Auto-generated method stub Patient p1=new Patient("John",2); Patient p2=new Patient("Tom",9); Patient p3=new Patient("Jack",4); Patient p4=new Patient("Michael",6); MyPriorityQueue<Patient> priorityQueue=new MyPriorityQueue<>(); priorityQueue.enqueue(p1); priorityQueue.enqueue(p2); priorityQueue.enqueue(p3); priorityQueue.enqueue(p4); while(priorityQueue.getSize()>0){ System.out.print(priorityQueue.dequeue()+" "); } } static class Patient implements Comparable{ private String name; private int priority; public Patient(String name,int priority){ this.name=name; this.priority=priority; } public String toString(){ return name+"(priority:"+priority+")"; } @Override public int compareTo(Object oo) {//比較優先順序 // TODO Auto-generated method stub return this.priority-((Patient)oo).priority; } } }
測試結果:優先順序高的先輸出,優先順序最高的就是堆的根節點