摘要:我理解的數(shù)據(jù)結(jié)構(gòu)三隊(duì)列一隊(duì)列隊(duì)列是一種線性結(jié)構(gòu)相比數(shù)組,隊(duì)列對(duì)應(yīng)的操作是數(shù)組的子集只能從一端隊(duì)尾添加元素,只能從另一端隊(duì)首取出元素隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)二數(shù)組隊(duì)列與循環(huán)隊(duì)列數(shù)組隊(duì)列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會(huì)發(fā)
我理解的數(shù)據(jù)結(jié)構(gòu)(三)—— 隊(duì)列(Queue) 一、隊(duì)列
隊(duì)列是一種線性結(jié)構(gòu)
相比數(shù)組,隊(duì)列對(duì)應(yīng)的操作是數(shù)組的子集
只能從一端(隊(duì)尾)添加元素,只能從另一端(隊(duì)首)取出元素
隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)(FIFO)
二、數(shù)組隊(duì)列與循環(huán)隊(duì)列 1. 數(shù)組隊(duì)列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會(huì)發(fā)現(xiàn),自己封裝一個(gè)數(shù)組隊(duì)列是如此的輕松加愉快!
(1)先定義一個(gè)接口,接口中定義隊(duì)列需要實(shí)現(xiàn)的方法
public interface Queue{ int getSize(); boolean isEmpty(); // 查看隊(duì)首元素 E getFront(); // 入隊(duì) void enqueue(E ele); // 出隊(duì) E dequeue(); }
(2)實(shí)現(xiàn)數(shù)組隊(duì)列
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ù)組隊(duì)列的復(fù)雜度
方法 | 復(fù)雜度 |
---|---|
enqueue | O(1) 均攤 |
dequeue | O(n) |
front | O(1) |
getSize | O(1) |
isEmpty | O(1) |
這個(gè)時(shí)候我們會(huì)發(fā)現(xiàn),在進(jìn)行出隊(duì)操作的時(shí)候,數(shù)組隊(duì)列的復(fù)雜度是0(n),如果我們頻繁的進(jìn)行出隊(duì)操作,那么其實(shí)數(shù)組隊(duì)列的效率是很低的,如何提升數(shù)組隊(duì)列的性能呢?這個(gè)時(shí)候我們就要用到循環(huán)隊(duì)列了。2. 循環(huán)隊(duì)列隊(duì)列
循環(huán)隊(duì)列的原理:
dequeue時(shí),不要在去除隊(duì)首元素時(shí),把整體向前移動(dòng)
維護(hù) front 、 tail 和 size 這三個(gè)屬性
enqueue的時(shí)候tail++
dequeue的時(shí)候front++
(1)實(shí)現(xiàn)循環(huán)隊(duì)列
public class LoopQueueimplements Queue { private E[] array; private int size; private int front; private int tail; public LoopQueue(int capacity) { // 我們需要浪費(fèi)一個(gè)空間去判斷隊(duì)列是否已滿,所以需要把capacity + 1 array = (E[])new Object[capacity + 1]; front = 0; tail = 0; size = 0; } public LoopQueue() { this(10); } // 返回用戶傳遞的隊(duì)列大小 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ò)展隊(duì)列長(zhǎng)度為原長(zhǎng)度2倍 resize(getCapacity() * 2); } array[tail] = ele; size++; tail = (tail + 1) % array.length; } @Override public E dequeue() { if (isEmpty()) { // 隊(duì)列為空 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)隊(duì)列的復(fù)雜度
方法 | 復(fù)雜度 |
---|---|
enqueue | O(1) 均攤 |
dequeue | O(1) 均攤 |
front | O(1) |
getSize | O(1) |
isEmpty | O(1) |
(1)用時(shí)方法
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)用
// 十萬次入隊(duì)和十萬次出隊(duì)操作 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
這個(gè)就是算法和數(shù)據(jù)結(jié)構(gòu)的力量!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/29300.html
摘要:我理解的數(shù)據(jù)結(jié)構(gòu)三隊(duì)列一隊(duì)列隊(duì)列是一種線性結(jié)構(gòu)相比數(shù)組,隊(duì)列對(duì)應(yīng)的操作是數(shù)組的子集只能從一端隊(duì)尾添加元素,只能從另一端隊(duì)首取出元素隊(duì)列是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)二數(shù)組隊(duì)列與循環(huán)隊(duì)列數(shù)組隊(duì)列如果你有看過我之前的文章不要小看了數(shù)組或者棧,你就會(huì)發(fā) 我理解的數(shù)據(jù)結(jié)構(gòu)(三)—— 隊(duì)列(Queue) 一、隊(duì)列 隊(duì)列是一種線性結(jié)構(gòu) 相比數(shù)組,隊(duì)列對(duì)應(yīng)的操作是數(shù)組的子集 只能從一端(隊(duì)尾)添加元素,...
摘要:后續(xù)介紹交換機(jī),生產(chǎn)者直接將消息投遞到中。消息,服務(wù)器和應(yīng)用程序之間傳送的數(shù)據(jù),由和組成。也稱為消息隊(duì)列,保存消息并將它們轉(zhuǎn)發(fā)給消費(fèi)者。主要是應(yīng)為和有一個(gè)綁定的關(guān)系。 showImg(https://img-blog.csdnimg.cn/20190509221741422.gif); showImg(https://img-blog.csdnimg.cn/20190731191914...
摘要:一前言上一篇已經(jīng)講過了鏈表實(shí)現(xiàn)單向鏈表了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用棧和隊(duì)列如果寫錯(cuò)的地方希望大家能夠多多體諒并指正哦,如果有更好的理解的方式也希望能夠在評(píng)論下留言,讓大家學(xué)習(xí)學(xué)習(xí)二數(shù)據(jù)結(jié)構(gòu)棧就是這么簡(jiǎn)單數(shù)據(jù)結(jié)構(gòu) 一、前言 上一篇已經(jīng)講過了鏈表【Java實(shí)現(xiàn)單向鏈表】了,它跟數(shù)組都是線性結(jié)構(gòu)的基礎(chǔ),本文主要講解線性結(jié)構(gòu)的應(yīng)用:棧和隊(duì)列 如果寫錯(cuò)的地方希望大家...
摘要:之?dāng)?shù)組操作接下來就是數(shù)據(jù)結(jié)構(gòu)的第一部分,棧。以字符串顯示棧中所有內(nèi)容方法的實(shí)現(xiàn)說明需要往棧中添加新元素,元素位置在隊(duì)列的末尾。的前端樂園原文鏈接寒假前端學(xué)習(xí)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法,棧與隊(duì)列 本系列的第一篇文章: 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一),棧與隊(duì)列第二篇文章:學(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ǔ)知識(shí)。這本書用了我最熟悉的來實(shí)現(xiàn)各種數(shù)據(jù)結(jié)構(gòu)和算法,而且書很薄,可以說是一本不錯(cuò)的入門教程。隊(duì)列在頭部刪除元素,尾部添加元素。 本系列所有文章:第一篇文章:學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法之棧與隊(duì)列第二篇文章:學(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)與算...
閱讀 3028·2023-04-25 18:00
閱讀 2237·2021-11-23 10:07
閱讀 4081·2021-11-22 09:34
閱讀 1256·2021-10-08 10:05
閱讀 1579·2019-08-30 15:55
閱讀 3449·2019-08-30 11:21
閱讀 3352·2019-08-29 13:01
閱讀 1392·2019-08-26 18:26