欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java循環(huán)隊(duì)列原理與用法詳解

 更新時(shí)間:2020年03月17日 08:44:21   作者:WFaceBoss  
這篇文章主要介紹了Java循環(huán)隊(duì)列原理與用法,結(jié)合實(shí)例形式詳細(xì)分析了Java循環(huán)隊(duì)列基本概念、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了Java循環(huán)隊(duì)列原理與用法。分享給大家供大家參考,具體如下:

在正式進(jìn)行循環(huán)隊(duì)列學(xué)習(xí)之前,我們先來看看在順序隊(duì)列中刪除隊(duì)首元素出現(xiàn)的問題

(1)設(shè)一個(gè)容量為capacity=8,size=5(a,b,c,d,e)的數(shù)組,左側(cè)為隊(duì)首、右側(cè)為隊(duì)尾。

(2)出隊(duì)一個(gè)元素后,需整體往前移動(dòng)一位

#出隊(duì)

  

#2整體前移一位

關(guān)于該種操作方式我們很容易得出時(shí)間復(fù)雜度為O(n)。

這時(shí)我們就想可不可以在出隊(duì)元素后,整體元素不往前移,而是在數(shù)組中記下隊(duì)首front是誰,同時(shí)隊(duì)尾tail指向在下一次元素入隊(duì)時(shí)的位置,這樣當(dāng)再有出隊(duì)時(shí)只需要維護(hù)一下front的指向即可,而不需移動(dòng)元素。就這樣我們就有了循環(huán)隊(duì)列的情況。

2.循環(huán)隊(duì)列原理

(1)初始,數(shù)組整體為空時(shí),隊(duì)首front、隊(duì)尾tail指向同一個(gè)位置(數(shù)組索引為0的地方)也即front==tail 時(shí)隊(duì)列為空

 

(2)當(dāng)往數(shù)組中添加元素后,

(3)出隊(duì)一個(gè)元素,front指向新的位置

(4)入隊(duì)元素,tail疊加

(5)當(dāng)tail不能再增加時(shí),數(shù)組前面還有空余,此時(shí)循環(huán)隊(duì)列就該出場(chǎng)了。

 

此時(shí)數(shù)組應(yīng)該變?yōu)檫@樣:

 在往數(shù)組中添加一個(gè)元素:

這樣數(shù)組就已經(jīng)滿了(tail+1==front 隊(duì)列滿),開始出發(fā)擴(kuò)容操作?!綾apacity中,浪費(fèi)一個(gè)空間】。

為了tail能返回到數(shù)組的前面位置,將隊(duì)列滿的表達(dá)式變?yōu)?【(tail+1)%c==front】這樣數(shù)組就可以循環(huán)移動(dòng)了。

3.循環(huán)隊(duì)列代碼實(shí)現(xiàn)

新建一個(gè)類LoopQueue并實(shí)現(xiàn)接口Queue。

#1:接口Queue代碼如下:

package Queue;

public interface Queue<E> {
  //獲取隊(duì)列中元素個(gè)數(shù)
  int getSize();

  //隊(duì)列中元素是否為空
  boolean isEmpty();

  //入隊(duì)列
  void enqueue(E e);

  //出隊(duì)列
  E dequeue();

  //獲取隊(duì)首元素
  E getFront();
}

#2:LoopQueue相關(guān)代碼:

package Queue;

//循環(huán)隊(duì)列
public class LoopQueue<E> implements Queue<E> {
  private E[] data;
  private int front, tail;
  private int size;//隊(duì)列中元素個(gè)數(shù)

  //構(gòu)造函數(shù),傳入隊(duì)列的容量capacity構(gòu)造函數(shù)
  public LoopQueue(int capacity) {
    data = (E[]) new Object[capacity + 1];//浪費(fèi)與一個(gè)空間
    front = 0;
    tail = 0;
    size = 0;
  }

  //無參構(gòu)造函數(shù),默認(rèn)隊(duì)列的容量capacity=10
  public LoopQueue() {
    this(10);
  }

  //真正容量
  public int getCapacity() {
    return data.length - 1;
  }

  //隊(duì)列是否為空
  @Override
  public boolean isEmpty() {
    return front == tail;
  }

  //隊(duì)列中元素個(gè)數(shù)
  @Override
  public int getSize() {
    return size;
  }

  //入隊(duì)列操作
  @Override
  public void enqueue(E e) {
    if ((tail + 1) % data.length == front) {//隊(duì)列已滿,需要擴(kuò)容
      resize(getCapacity() * 2);
    }
    data[tail] = e;
    tail = (tail + 1) % data.length;
    size++;
  }

  //出隊(duì)操作

  @Override
  public E dequeue() {
    if (isEmpty()) {
      throw new IllegalArgumentException("隊(duì)列為空");
    }

    E ret = data[front];
    data[front] = null;//手動(dòng)釋放
    front = (front + 1) % data.length;
    size--;
    if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {
      resize(getCapacity() / 2);
    }
    return ret;
  }

  //獲取隊(duì)首元素
  @Override
  public E getFront() {
    if (isEmpty()) {
      throw new IllegalArgumentException("隊(duì)列為空");
    }
    return data[front];
  }

  //改變?nèi)萘?
  private void resize(int newCapacity) {
    E[] newData = (E[]) new Object[newCapacity + 1];
    for (int i = 0; i < size; i++) {
      newData[i] = data[(front + i) % data.length];//循環(huán)數(shù)組防止越界
    }
    data = newData;
    front = 0;
    tail = size;
  }


  @Override
  public String toString() {
    StringBuilder res = new StringBuilder();
    res.append(String.format("Queue:size=%d, capacity=%d\n", size, getCapacity()));
    res.append("front [");
    for (int i = front; i != tail; i = (i + 1) % data.length) {
      res.append(data[i]);
      if ((i + 1) % data.length != tail) {
        res.append(",");
      }
    }
    res.append("] tail");
    return res.toString();
  }



}

在關(guān)于LoopQueue類中需要注意的:

(1)第11行中的+1是capacity需要浪費(fèi)一個(gè)空間,故在實(shí)例化是多加1

 data = (E[]) new Object[capacity + 1];//浪費(fèi)與一個(gè)空間

(2)地24行真正的容量是data.length-1,這是由于有一個(gè)空間是浪費(fèi)的。

data.length - 1;

(3)關(guān)于入隊(duì)中第46行tail值的說明

為了保證入隊(duì)是循環(huán)操作,tail值的變化規(guī)律為

 tail = (tail + 1) % data.length;

(4)關(guān)于82行的數(shù)據(jù)遷移操作,取余操作是為了防止循環(huán)數(shù)組時(shí)越界。

  newData[i] = data[(front + i) % data.length];//循環(huán)數(shù)組防止越界

#3直接在LoopQueue中添加一個(gè)main函數(shù)進(jìn)行測(cè)試,相關(guān)代碼如下:

  //測(cè)試用例
  public static void main(String[] args) {
    LoopQueue<Integer> queue = new LoopQueue<Integer>();
    for (int i = 0; i < 10; i++) {
      queue.enqueue(i);
      System.out.println(queue);

      if(i%3==2){//每添加3個(gè)元素出隊(duì)列一個(gè)
        queue.dequeue();
        System.out.println(queue);
      }

    }

  }

結(jié)果為:

 

4.循環(huán)隊(duì)列時(shí)間復(fù)雜度

到此我們就實(shí)現(xiàn)了一個(gè)循環(huán)隊(duì)列操作,解決了在順序隊(duì)列中出隊(duì)時(shí)的時(shí)間復(fù)雜度為O(n)的情況,在循環(huán)隊(duì)列中出隊(duì)的時(shí)間復(fù)雜度為O(1)。

源碼地址 https://github.com/FelixBin/dataStructure/blob/master/src/Queue/LoopQueue.java

更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • 使用React和springboot做前后端分離項(xiàng)目的步驟方式

    使用React和springboot做前后端分離項(xiàng)目的步驟方式

    這篇文章主要介紹了使用React和springboot做前后端分離項(xiàng)目的步驟方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java可以寫android的應(yīng)用程序嗎

    Java可以寫android的應(yīng)用程序嗎

    在本篇文章里小編給大家整理的是一篇關(guān)于Java可以寫android的應(yīng)用程序嗎的相關(guān)基礎(chǔ)文章,有興趣的朋友們可以學(xué)習(xí)下。
    2020-11-11
  • Maven根據(jù)不同環(huán)境打包不同配置文件的方法

    Maven根據(jù)不同環(huán)境打包不同配置文件的方法

    這篇文章主要介紹了Maven根據(jù)不同環(huán)境打包不同配置文件的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • Spring?Boot?+?Spring?Batch?實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程

    Spring?Boot?+?Spring?Batch?實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程

    這篇文章主要介紹了Spring?Boot+Spring?Batch實(shí)現(xiàn)批處理任務(wù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 關(guān)于Java集合框架Collection接口詳解

    關(guān)于Java集合框架Collection接口詳解

    這篇文章主要介紹了關(guān)于Java集合框架Collection接口詳解,Collection接口是Java集合框架中的基礎(chǔ)接口,定義了一些基本的集合操作,包括添加元素、刪除元素、遍歷集合等,需要的朋友可以參考下
    2023-05-05
  • SpringBoot在 POM 中引入本地 JAR 包的方法

    SpringBoot在 POM 中引入本地 JAR 包的方法

    在開發(fā) Spring Boot 應(yīng)用程序時(shí),您可能需要使用本地 JAR 包來添加自定義庫或功能,本文將介紹在 Spring Boot 項(xiàng)目的 POM 文件中如何引入本地 JAR 包,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • Java CPU性能分析工具代碼實(shí)例

    Java CPU性能分析工具代碼實(shí)例

    這篇文章主要介紹了Java CPU性能分析工具代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java實(shí)現(xiàn)簡單臺(tái)球游戲

    Java實(shí)現(xiàn)簡單臺(tái)球游戲

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡單臺(tái)球游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡單實(shí)例

    Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡單實(shí)例

    下面小編就為大家?guī)硪黄狫ava實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • Java基礎(chǔ)教程之包(package)

    Java基礎(chǔ)教程之包(package)

    這篇文章主要介紹了Java基礎(chǔ)教程之包(package),本文詳細(xì)講解了包的創(chuàng)建、使用等方法,需要的朋友可以參考下
    2014-08-08

最新評(píng)論