2018年學習總結博客總目錄:第一週 第二週 第三週
html
1.隊列是一種線性集合,其元素從一端加入,從另外一端刪除;隊列元素是按先進先出(FIFO(First in First out))方式進行處理的。前端
2.隊列ADT所定義的一些基本操做,見下表java
操做 | 描述 |
---|---|
enqueue | 向列表末端添加一個元素 |
dequeue | 從隊列前端刪除一個元素 |
first | 考察隊列前端的那個元素 |
isEmpty | 斷定隊列是否爲空 |
size | 斷定隊列中的元素數目 |
toString | 返回隊列的字符串表示 |
3.Java API中的隊列
java.util包中有接口 Queue
4.隊列的兩個應用:代碼密鑰,售票口模擬。git
5.隊列ADT
咱們定義一個泛型QueueADT接口,表示隊列的操做,把操做的通常目標與各類實現方式分開。下面是其UML描述:
下面爲其代碼:編程
public interface QueueADT<T> { public void enqueue(T elem); public T dequeue(); public T first(); public boolean isEmpty(); public int size(); public String toString(); }
6.用鏈表實現隊列數組
import jsjf.*; public class LinkedQueue<T> implements QueueADT<T> { private int count; private LinearNode<T> head,tail; public LinkedQueue() { count = 0 ; head = tail = null; }
public void enqueue(T element) { LinearNode<T> node = new LinearNode<T>(element); if (isEmpty()) head = node; else tail.setNext(node); tail = node; count++; }
public T dequeue() throws EmptyCollectionException { if (isEmpty()) throw new EmptyCollectionException("queue"); T result = head.getElement(); head = head.getNext(); count--; if (isEmpty()) tail = null; return result; }
7.用數組實現隊列ide
這裏咱們首先考慮一個通常數組,因爲隊列操做會修改集合的兩端,所以要將一端固定於索引爲0處移動元素,這樣便有兩種可能:(1)首元素永遠固定在數組索引爲0處,這時添加元素時複雜度爲O(1),而刪除元素時,複雜度將會變爲O(n);(2)隊列的末元素始終固定在數組索引爲0處,這時刪除一個元素時複雜度爲O(1),而添加一個新元素時則會使複雜度變爲O(n)。不管以上哪一種狀況,都不是最好的解決辦法。這時,咱們能夠去採用環形數組(circular array)來實現隊列,即一種環形的數組結構。單元測試
public class CircularArrayQueue<T> implements QueueADT<T> { private final static int DEFAULT_CAPACITY = 100; private int front, rear, count; private T[] queue; /** * Creates an empty queue using the specified capacity. * @param initialCapacity the initial size of the circular array queue */ public CircularArrayQueue (int initialCapacity) { front = rear = count = 0; queue = (T[]) (new Object[initialCapacity]); } /** * Creates an empty queue using the default capacity. */ public CircularArrayQueue() { this(DEFAULT_CAPACITY); }
rear的值表明數組的下一個可用單元。學習
rear = (rear+1) % queue.length;
,同時,當數組中的全部單元已經填充,這時就須要擴容這一操做,否則新元素會覆蓋掉以前的首元素。public void enqueue(T element) { if (size() == queue.length) expandCapacity(); queue[rear] = element; rear = (rear+1) % queue.length; count++; } /** * Creates a new array to store the contents of this queue with * twice the capacity of the old one. */ private void expandCapacity() { T[] larger = (T[]) (new Object[queue.length *2]); for (int scan = 0; scan < count; scan++) { larger[scan] = queue[front]; front = (front + 1) % queue.length; } front = 0; rear = count; queue = larger; }
public T dequeue() throws EmptyCollectionException { if (isEmpty()) throw new EmptyCollectionException("queue"); T result = queue[front]; queue[front] = null; front = (front+1) % queue.length; count--; return result; }
8.雙端隊列
雙端隊列(deque)是隊列的拓展,它容許從隊列的兩端添加、刪除和查看元素。
Customer customer; Queue<Customer> customerQueue = new LinkedList<Customer>(); int[] cashierTime = new int[MAX_CASHIERS]; //收銀員的時間標記 int totalTime, averageTime, departs,start; /** process the simulation for various number of cashiers */ for (int cashiers = 0; cashiers < MAX_CASHIERS; cashiers++) { /** set each cashiers time to zero initially */ for (int count = 0; count < cashiers; count++) cashierTime[count] = 0; /** load customer queue */ for (int count = 1; count <= NUM_CUSTOMERS; count++) customerQueue.offer(new Customer(count * 15)); totalTime = 0;//使用的整體時間 /** process all customers in the queue */ while (!(customerQueue.isEmpty())) { for (int count = 0; count <= cashiers; count++) { if (!(customerQueue.isEmpty())) { customer = customerQueue.poll(); if (customer.getArrivalTime() > cashierTime[count]) start = customer.getArrivalTime() ; else start = cashierTime[count]; // 離開時間的設置 departs = start + PROCESS; customer.setDepartureTime(departs); cashierTime[count] = departs; //每一個顧客使用的最總時間 totalTime += customer.totalTime(); } } } averageTime = totalTime / NUM_CUSTOMERS; System.out.println("Number of cashiers: " + (cashiers + 1)); System.out.println("Average time: " + averageTime + "\n"); }
for (int cashiers = 0; cashiers < MAX_CASHIERS; cashiers++) {}
,這是最外層的一個循環,這個循環要完成的是模擬售票口數量,從1開始到10結束,那麼咱們如今能夠先把它固定下來,假定如今cashiers=4,而後繼續;for (int count = 0; count < cashiers; count++) cashierTime[count] = 0; /** load customer queue */ for (int count = 1; count <= NUM_CUSTOMERS; count++) customerQueue.offer(new Customer(count * 15)); totalTime = 0;//使用的整體時間
這幾行代碼是將每一個cashier time初始化爲0,同時再導入每位顧客來的時間,整體時間設爲0,而後繼續;
到了這裏while (!(customerQueue.isEmpty())){}
,又是一個較大的循環,當隊列不爲空時,售票口就須要處理,繼續;
再內層的for (int count = 0; count <= cashiers; count++) {}
這個循環模擬的是各個售票口進行處理,咱們剛纔固定cashiers爲4,那麼這個循環就會進行5次,此時各個售票口進行處理;
而後,
customer = customerQueue.poll(); if (customer.getArrivalTime() > cashierTime[count]) start = customer.getArrivalTime() ; else start = cashierTime[count]; departs = start + PROCESS; customer.setDepartureTime(departs); cashierTime[count] = departs; //每一個顧客使用的最總時間 totalTime += customer.totalTime();
這裏是我理解起來最費力氣的一個地方,首先是一位顧客出隊進行辦理,咱們要計算他在這裏的等待時間,好比說第第150秒來的顧客,他剛好走到了第3個售票口,那麼若是他來的時間是在前一位顧客已經離開以後,那麼他將不用等待,之間記開始start爲他來的時間,而後加上他處理的時間,就是他離開的時間;那麼,若是他來的時候,前面還有顧客沒有處理完,那麼這時就有等待時間了,等待的時間就是這個售票口處所記的counterTime,再加上他的處理時間,就是他離開的時間。後面的就比較容易理解了,再也不敘述。
這樣就完成了整個的售票口的一個模擬流程,獲得了書上的結果。
問題:關於書上習題PP5.7,其中要求的雙端隊列能夠用單鏈表實現,不會用雙向鏈表進行實現。
問題解決方案:暫時還不會。雙向鏈表不知道previous這個節點該怎麼去使用,還不會解決。學會後補這裏解決方案。
————————————————-————————————————————-
class Link { public long dData; public Link next; public Link(long dData) { this.dData = dData; } public void displayLink() { System.out.print("{" + this.dData + "}"); } }
首先是建立一個節點類,而後創建一個鏈表;
class FirstLastList { Link first; Link last; public FirstLastList() { this.first = null; //when create an object of LinkList,make sure it is empty! this.last = null; } public boolean isEmpty() { return first == null; } public void insertLast(long key) //this method will be used when I create insert() method { //in Queue(not the class Queue,I just mean a Queue) Link newLink = new Link(key); if(this.isEmpty()) //if list is empty { first = newLink; //draw a picture can help me understand it ! last = newLink; newLink.next = null; } else { last.next = newLink; last = newLink; newLink.next = null; } } public long deleteFirst() //this method will be used when I create remove() method in Queue(not the class Queue,I just mean a Queue) { Link current = null; if(this.isEmpty()) { System.out.println("Your stack is empty"); return -1; } else if(first==last) { current = first; first = null; last = null; return current.dData; } else { current = first; first = first.next; return current.dData; } } public void displayList() { Link current = first; System.out.print("Queue (front-->rear): "); if(this.isEmpty()) { System.out.println("Your list is empty, nothing to show!"); } else { while(current!=null) { current.displayLink(); current = current.next; } System.out.println(""); } } } class LinkQueue { FirstLastList list = new FirstLastList(); //two-ended list public void insert(long key) { list.insertLast(key); } public long remove() { return list.deleteFirst(); } public void showQueue() { list.displayList(); } } class LinkQueueApp { public static void main(String[] args) { LinkQueue theQueue = new LinkQueue(); theQueue.insert(12); //insert four elements theQueue.insert(13); theQueue.insert(14); theQueue.insert(15); theQueue.showQueue(); //look at what is in the queue theQueue.remove(); //remove two elements ,from right side theQueue.remove(); theQueue.showQueue(); //look at what is in the queue now! } }
雙端鏈表其實是比單鏈表多了一個指向最後一個節點的引用,其餘的實現與單鏈表相同。
上週代碼行數爲8255行,如今爲8867行,本週共612行
1.By using the interface name as a return type, the interface doesn’t commit the method to the use of any particular class that implements a stack.(正確)
解析:經過使用接口名做爲return類型,接口不會將該方法提交給任何實現堆棧的特定類。
2.The implementation of the collection operations should affect the way users interact with the collection.(錯誤)
解析:集合的操做方式不可以影響用戶與集合元素的交互方式。
3.Inherited variables and methods can be used in the derived class as if they had been declared locally.(正確)
解析:繼承的變量和方法能夠在派生類中使用,就如它們是本地聲明的同樣。
博客中值得學習的或問題: 博客中代碼問題解決過程記錄較詳細,可適當添加教材內容總結。
結對學習內容:學習第5章內容——隊列
技能 | 課前評估 | 課後但願值 |
---|---|---|
對編程的總體理解 | 2 | 6 |
程序理解 | 4 | 8 |
單元測試、代碼覆蓋率 | 1 | 6 |
效能分析和改進 | 3 | 7 |
需求分析 | 0 | 5 |
計劃任務 | 2 | 7 |
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 15/15 | |
第二週 | 572/572 | 1/2 | 16/31 | |
第三週 | 612/1184 | 1/3 | 13/44 |