摘要:我理解的數(shù)據(jù)結(jié)構(gòu)三隊列一隊列隊列是一種線性結(jié)構(gòu)相比數(shù)組,隊列對應(yīng)的操作是數(shù)組的子集只能從一端隊尾添加元素,只能從另一端隊首取出元素隊列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)二數(shù)組隊列與循環(huán)隊列數(shù)組隊列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會發(fā)
我理解的數(shù)據(jù)結(jié)構(gòu)(三)—— 隊列(Queue) 一、隊列
隊列是一種線性結(jié)構(gòu)
相比數(shù)組,隊列對應(yīng)的操作是數(shù)組的子集
只能從一端(隊尾)添加元素,只能從另一端(隊首)取出元素
隊列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)(FIFO)
二、數(shù)組隊列與循環(huán)隊列 1. 數(shù)組隊列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會發(fā)現(xiàn),自己封裝一個數(shù)組隊列是如此的輕松加愉快!
(1)先定義一個接口,接口中定義隊列需要實現(xiàn)的方法
public interface Queue{ int getSize(); boolean isEmpty(); // 查看隊首元素 E getFront(); // 入隊 void enqueue(E ele); // 出隊 E dequeue(); }
(2)實現(xiàn)數(shù)組隊列
public class ArrayQueueimplements Queue { // 這里的數(shù)組是在之前的文章中封裝好的,直接拿來用就好了 private ArrayNew array; public ArrayQueue(int capacity) { array = new ArrayNew<>(capacity); } public ArrayQueue() { this(10); } public int getCapacity() { return array.getCapacity(); } @Override public int getSize() { return array.getSize(); } @Override public boolean isEmpty() { return array.isEmpty(); } @Override public E getFront() { return array.getFirst(); } @Override public void enqueue(E ele) { array.addLast(ele); } @Override public E dequeue() { return array.removeFirst(); } @Override public String toString() { StringBuffer res = new StringBuffer(); res.append(String.format("arrayQueue: size = %d, capacity = %d ", getSize(), getCapacity())); res.append("front ["); for (int i = 0; i < array.getSize(); i++) { res.append(array.get(i)); if (i != getSize() - 1) { res.append(", "); } } res.append("] tail"); return res.toString(); } }
(3)數(shù)組隊列的復(fù)雜度
方法 | 復(fù)雜度 |
---|---|
enqueue | O(1) 均攤 |
dequeue | O(n) |
front | O(1) |
getSize | O(1) |
isEmpty | O(1) |
這個時候我們會發(fā)現(xiàn),在進(jìn)行出隊操作的時候,數(shù)組隊列的復(fù)雜度是0(n),如果我們頻繁的進(jìn)行出隊操作,那么其實數(shù)組隊列的效率是很低的,如何提升數(shù)組隊列的性能呢?這個時候我們就要用到循環(huán)隊列了。2. 循環(huán)隊列隊列
循環(huán)隊列的原理:
dequeue時,不要在去除隊首元素時,把整體向前移動
維護(hù) front 、 tail 和 size 這三個屬性
enqueue的時候tail++
dequeue的時候front++
(1)實現(xiàn)循環(huán)隊列
public class LoopQueueimplements Queue { private E[] array; private int size; private int front; private int tail; public LoopQueue(int capacity) { // 我們需要浪費一個空間去判斷隊列是否已滿,所以需要把capacity + 1 array = (E[])new Object[capacity + 1]; front = 0; tail = 0; size = 0; } public LoopQueue() { this(10); } // 返回用戶傳遞的隊列大小 public int getCapacity() { return array.length - 1; } @Override public int getSize() { return size; } @Override public boolean isEmpty() { return front == tail; } @Override public E getFront() { if (isEmpty()) { throw new IllegalArgumentException("Queue is empty. Can"t get front."); } return array[0]; } @Override public void enqueue(E ele) { if (front == (tail + 1) % array.length) { // 擴(kuò)展隊列長度為原長度2倍 resize(getCapacity() * 2); } array[tail] = ele; size++; tail = (tail + 1) % array.length; } @Override public E dequeue() { if (isEmpty()) { // 隊列為空 throw new IllegalArgumentException("Queue is empty. Can"t get dequeue."); } E ele = array[front]; size--; array[front] = null; front = (front + 1) % array.length; if (size == getCapacity() / 4 && getCapacity() / 2 != 0) { resize(getCapacity() / 2); } return ele; } private void resize(int newCapacity) { E[] newArray = (E[]) new Object[newCapacity + 1]; for (int i = 0; i < size; i++) { newArray[i] = array[(front + i) % array.length]; } array = newArray; front = 0; tail = size; } @Override public String toString() { StringBuffer res = new StringBuffer(); res.append(String.format("queue: size = %d, capacity = %d ", getSize(), getCapacity())); res.append("front ["); // 循環(huán)條件,和循環(huán)增量都要注意下 for (int i = front; i != tail; i = (i + 1) % array.length) { res.append(array[i]); if ((i + 1) % array.length != tail) { res.append(", "); } } res.append("] tail"); return res.toString(); } }
(2)循環(huán)隊列的復(fù)雜度
方法 | 復(fù)雜度 |
---|---|
enqueue | O(1) 均攤 |
dequeue | O(1) 均攤 |
front | O(1) |
getSize | O(1) |
isEmpty | O(1) |
(1)用時方法
public static double test(Queueq, int opCount) { // 納秒 long startTime = System.nanoTime(); Random random = new Random(); for (int i = 0; i < opCount; i++) { q.enqueue(random.nextInt(Integer.MAX_VALUE)); } for (int i = 0; i < opCount; i++) { q.dequeue(); } // 納秒 long endTime = System.nanoTime(); return (endTime - startTime) / 1000000000.0; }
(2)調(diào)用
// 十萬次入隊和十萬次出隊操作 int opCount = 100000; ArrayQueueaq = new ArrayQueue<>(); double time1 = test(aq, opCount); System.out.println(time1); LoopQueue lq = new LoopQueue<>(); double time2 = test(lq, opCount); System.out.println(time2);
(3)結(jié)果
14.635995113
0.054536447
這個就是算法和數(shù)據(jù)結(jié)構(gòu)的力量!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/76846.html
摘要:我理解的數(shù)據(jù)結(jié)構(gòu)三隊列一隊列隊列是一種線性結(jié)構(gòu)相比數(shù)組,隊列對應(yīng)的操作是數(shù)組的子集只能從一端隊尾添加元素,只能從另一端隊首取出元素隊列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)二數(shù)組隊列與循環(huán)隊列數(shù)組隊列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會發(fā) 我理解的數(shù)據(jù)結(jié)構(gòu)(三)—— 隊列(Queue) 一、隊列 隊列是一種線性結(jié)構(gòu) 相比數(shù)組,隊列對應(yīng)的操作是數(shù)組的子集 只能從一端(隊尾)添加元素,...
摘要:后續(xù)介紹交換機(jī),生產(chǎn)者直接將消息投遞到中。消息,服務(wù)器和應(yīng)用程序之間傳送的數(shù)據(jù),由和組成。也稱為消息隊列,保存消息并將它們轉(zhuǎn)發(fā)給消費者。主要是應(yīng)為和有一個綁定的關(guān)系。 showImg(https://img-blog.csdnimg.cn/20190509221741422.gif); showImg(https://img-blog.csdnimg.cn/20190731191914...
摘要:一前言上一篇已經(jīng)講過了鏈表實現(xiàn)單向鏈表了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用棧和隊列如果寫錯的地方希望大家能夠多多體諒并指正哦,如果有更好的理解的方式也希望能夠在評論下留言,讓大家學(xué)習(xí)學(xué)習(xí)二數(shù)據(jù)結(jié)構(gòu)棧就是這么簡單數(shù)據(jù)結(jié)構(gòu) 一、前言 上一篇已經(jīng)講過了鏈表【Java實現(xiàn)單向鏈表】了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用:棧和隊列 如果寫錯的地方希望大家...
摘要:之?dāng)?shù)組操作接下來就是數(shù)據(jù)結(jié)構(gòu)的第一部分,棧。以字符串顯示棧中所有內(nèi)容方法的實現(xiàn)說明需要往棧中添加新元素,元素位置在隊列的末尾。的前端樂園原文鏈接寒假前端學(xué)習(xí)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法,棧與隊列 本系列的第一篇文章: 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一),棧與隊列第二篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(二):鏈表第三篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(三):集合第...
摘要:于是翻出了機(jī)房里的這本學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法開始學(xué)習(xí)程序員的基礎(chǔ)知識。這本書用了我最熟悉的來實現(xiàn)各種數(shù)據(jù)結(jié)構(gòu)和算法,而且書很薄,可以說是一本不錯的入門教程。隊列在頭部刪除元素,尾部添加元素。 本系列所有文章:第一篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊列第二篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之鏈表第三篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之集合第四篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之字典和散列表第五篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算...
閱讀 1603·2023-04-26 00:20
閱讀 1216·2023-04-25 21:49
閱讀 870·2021-09-22 15:52
閱讀 649·2021-09-07 10:16
閱讀 1030·2021-08-18 10:22
閱讀 2725·2019-08-30 14:07
閱讀 2295·2019-08-30 14:00
閱讀 2725·2019-08-30 13:00