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

資料結構-堆實現優先佇列(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();
    }
    
}
MyPriorityQueue.java
public 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();
       }
      
}
TestMyPriorityQueueMainClass.java
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;
		}
    	
    }
}

測試結果:優先順序高的先輸出,優先順序最高的就是堆的根節點