java_實現隊列以及實例


隊列的設計與實現及應用

一、目的和要求:

(1)正確定義隊列(順序隊或鏈隊);

(2)掌握隊列基本操作實現方法;

(3)能正確分析算法的時間復雜度;

(3)采用隊列解決實際問題。

二、實驗原理及內容:

(1)定義隊列(順序隊列或鏈隊列);

(2)隊列基本操作實現方法;

(3)采用隊列解決實際問題(銀行排隊叫號服務)。

三、實驗步驟:(以鏈隊列為例實現,也可以自行采用順序隊列實現)

(1)定義鏈隊列;

(2)鏈隊列基本操作實現方法;

(3)采用鏈隊列解決銀行排隊叫號服務問題。

 

四、實驗過程

1、工程結構如下圖所示:

 

2、隊列接口定義:IStack.java

public interface IQueue<E> {
    boolean in(E item);//入隊列操作
    E out(); //出隊列操作
    E head(); //取對頭元素
    int size();//求隊列的長度
    boolean isEmpty();//判斷隊列是否為空 
    boolean isFull();//判斷隊列是否為滿 
    void clear();//清空隊列
}


3、順序隊列的定義及實現:SeqQueue.java 

import java.lang.reflect.Array;
 
public class SeqQueue<E> implements IQueue<E> {
    private int maxsize; //隊列的容量
    private E[]data; // 存儲循環順序隊列中的數據元素
    private int front; // 指示最近一個己經離開隊列的元素所占的位置
    private int rear; // 指示最近一個進行入隊列的元素的位置
    private int size;
   
    public int getMaxsize() {
       returnmaxsize;
    }
    public void setMaxsize(int maxsize) {
       this.maxsize = maxsize;
    }
    public E[] getData() {
       returndata;
    }
    public void setData(E[] data) {
       this.data = data;
    }
    public int getFront() {
       returnfront;
    }
    public void setFront(int front) {
       this.front = front;
    }
    public int getRear() {
       returnrear;
    }
    public void setRear(int rear) {
       this.rear = rear;
    }
    //初始化隊列
    @SuppressWarnings("unchecked")
    public SeqQueue(Class<E> type,int maxsize) {
       data = (E[]) Array.newInstance(type,maxsize);
       this.maxsize = maxsize;
    }
    //入隊列操作
    public boolean in(E item) {
       if(isFull())return false;
       data[rear] = item;
       rear = (rear+1)%maxsize;
       size++;
       return true;
    }
   
     public int getSize() {
       returnsize;
    }
     
    public void setSize(int size) {
       this.size = size;
    }
    //出隊列操作
    public E out() {
        if(isEmpty())
        return null;
        E i = data[front];
        front = (front + 1)%maxsize;
        size--;
        return i;
    }
   
    //取對頭元素
    public E head() {
       if(isEmpty())
           return null;
       return
          data[front];
    }
    //求隊列的長度
    public int size() {
         return (rear+maxsize-front)%maxsize;
    }
    // 判斷隊列是否為空
    public boolean isEmpty() {
       if(front ==rear)
           return true;
       return false;
    }
    // 判斷循環順序隊列是否為滿
    public boolean isFull() {
       if(size ==maxsize)
           return true;
       return false;
    }
    //清空隊列
    public void clear() {
       size =0;
       front = rear = 0;
    }
}
 



4、順序隊列的測試:TestQueue.java 

public class TestQueue {
    public static void main(String[] args) {
       int[] data={23,45,3,7,6,945};
       //注意給定的循環隊列長度至少要比實際長度大1
       IQueue<Integer> queue=new SeqQueue<Integer>(Integer.class,data.length+1);
       //IQueue<Integer> queue=new LinkQueue<Integer>();
       //入隊操作
       System.out.println("*******入隊操作*******");
        for(int i=0; i<data.length;i++){
            queue.in(data[i]);
                System.out.println(data[i]+"入隊"); 
            } 
        int size=queue.size();
       //出隊操作
        System.out.println("*******出隊操作*******"); 
        for(int i=0; i<size;i++){ 
            System.out.println(queue.out()+"出隊 "); 
        } 
    }
}
 



5、鏈隊結點的定義 

class QueueNode<E>
{
    private Edata; // 數據域
    private QueueNode<E> next; // 引用域
    //get和set方法
    public E getData() {
       returndata;
    }
    public void setData(E data) {
       this.data = data;
    }
    public QueueNode<E> getNext() {
       returnnext;
    }
    public void setNext(QueueNode<E> next) {
       this.next = next;
    }
     //構造函數
    public QueueNode(){}
    public QueueNode(E data) {
       this.data = data;
    }
    public QueueNode(E data,QueueNode<E> next) {
       this.data = data;
       this.next = next;
    }
   
}

6、鏈隊的定義及實現

public class LinkQueue<E> implements IQueue<E> {
    private QueueNode<E>front; // 隊列頭指示器
    private QueueNode<E>rear; // 隊列尾指示器
    private int size; // 隊列數據元素個數
 
    // 初始化鏈隊列
    public LinkQueue() {
       front = rear = null;
       size = 0;
    }
 
    // 入隊列操作
    public boolean in(E item) {
       QueueNode<E> q = new QueueNode<E>(item);
       if(front ==null)
       {
           front = rear = q;
       }else{
          rear.setNext(q);
          rear = q;
       }
       size++;
        return true;
    }
 
    // 出隊列操作
    public E out() {
       if(size == 0)
           return null;
       E i = front.getData();
       front = front.getNext();
       size--;
       return i;
    }
 
    // 取對頭元素
    public E head() {
       returnfront.getData();
    }
 
    // 求隊列的長度
    public int size() {
       returnsize;
    }
 
    // 判斷隊列是否為空
    public boolean isEmpty() {
       if(rear ==front)
return true;
       return false;
    }
 
    //清空隊列
    public void clear() {
       front = rear = null;
       size =0;
    }
}
 


7、銀行叫號實現(排隊機) 

public class TestBankQueue {
    public static void main(String[] args){
         int windowcount =2;//設置銀行櫃台的服務窗口數。先設為1,然后依次增加看效果
         //創建服務窗口數組
          ServiceWindow[] sw = new ServiceWindow[windowcount];
         //創建排隊機對象
          QueueMachine qm=new QueueMachine("0800","1630");
          //啟動排隊機服務
          qm.start();
          for (int i = 0; i < windowcount; i++)
          {
            //初始化服務窗口數組
            sw[i] = new ServiceWindow(qm.getQueue());
            //將名字設置為服務窗口的編號
            sw[i].setName( "" + (i + 1));
            //啟動窗口服務
            sw[i].start();
          }
             
    }
}
 


8、銀行叫號實現(測試主類)

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Scanner;
 
public class QueueMachine extends Thread {
    private int number;//排隊機當前最新號碼
    private IQueue<Integer> queue;//排隊機維持的隊列
    private String starttime;//排隊機工作開始時間,例如:0800為早上8點
    private String endtime;//排隊機工作結束進間例如:1630為下午4點半
    public QueueMachine( String starttime,String endtime){
        queue=new SeqQueue<Integer>(Integer.class,100);
        //queue=new LinkQueue<Integer>();
        this.starttime=starttime;
        this.endtime=endtime;
    }
    //獲取服務隊列
    public IQueue<Integer> getQueue() {
            return queue;
    }
    //顧客按回車獲取服務號,將服務號入隊、打印服務小票
    public void run(){
         Scanner sc=new Scanner(System.in);
         SimpleDateFormat df = new SimpleDateFormat("HHmm");//設置日期格式
        //獲取當前系統時間並轉換為設置的日期格式
         String time=df.format(new Date());
         while (time.compareTo(starttime)>=0 && time.compareTo(endtime)<=0)
          {
            System.out.println("按回車鍵獲取號碼:");
            sc.nextLine(); 
            int callnumber=++number;  
             if (queue.in(callnumber))
                {
                   System.out.println(String.format("您的號碼是:%d,你前面有%d位,請等待!", callnumber,  queue.size()-1));
                   time=df.format(new Date());
                }
             else{
                   System.out.println("現在業務繁忙,請稍后再試!"); //隊列滿時出現這種情況
                   number--;
             }
          }
        sc.close();
        System.out.println("己到下班時間,請明天再來");    
    }
}

9、銀行叫號實現(服務窗口)

 
public class ServiceWindow extends Thread {
    private IQueue<Integer>queue;//服務隊列
    //在構造函數中指定服務的隊列
    public ServiceWindow(IQueue<Integer>queue) {
       this.queue =queue;
    }
    //窗口叫號及銀行櫃台人員工作時間10000ms
    public void run() {
       while (true) {
           synchronized (queue) {
              if (queue.size()>0) {
                  System.out.println(String.format("請%d號到%s號窗口!",
                         queue.out(), Thread.currentThread().getName()));
              }
           }
           try {
              Thread.sleep(10000);
           } catch (InterruptedException e) {
              System.out.println(e.getMessage());
           }
       }
    }
}
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM