OO第三單元總結

OO第三單元總結

梳理JML語言的理論基礎、應用工具鏈狀況

JML(Java Modeling Language)是一種行爲規範接口語言,經過使用不會被編譯的註釋形式,和固定關鍵字的語法,指定Java模塊代碼的行爲。大致上包括如下三種要求:java

前置: @requires 子句定義了須要知足的條件。node

過程: @assignment 子句定義了能夠改變的成員。算法

後置: @ensure 子句定義了方法要達到的效果。數組

此外,還有一些比較經常使用的的語法以下:數據結構

@pure 子句代表該方法無反作用,即僅具備查詢功能架構

@constraint 子句定義了狀態變化約束框架

@invariant 子句定義了全過程當中的不變式函數

\nothing 關鍵詞代表該方法對類成員屬性不進行修改工具

\result 關鍵詞表明該方法的返回值學習

\forall表達式:全稱量詞修飾的表達式,表示對於給定範圍內的元素,每一個元素都知足相應的約束。

\exists表達式: 存在量詞修飾的表達式,表示對於給定範圍內的元素,存在某個元素知足相應的約束。

\sum表達式:返回給定範圍內的表達式的和。

\product表達式:返回給定範圍內的表達式的連乘結果。

\max表達式:返回給定範圍內的表達式的最大值。

\min表達式:返回給定範圍內的表達式的最小值。

\num_of表達式:返回指定變量中知足相應條件的取值個數。

JML的應用工具鏈:

OpenJML:OpenJML能夠對含有JML的代碼進行編譯 ,並提供不一樣類型的選項進行檢查。-esc能夠靜態檢查可能出現的隱藏bug,-rac是運行時檢查,-check則能夠檢查代碼是否符合JML規格要求。

JMLUnitNG:能夠根據代碼中所寫JML規範自動生成測試框架進行自動化測試。

部署JMLUnitNG/JMLUnit,針對Graph接口的實現自動生成測試用例

測試結果以下:

三次做業架構設計

第一次做業架構設計

本次做業徹底根據規格要求進行設計,爲了減小查詢的時間,採用了hashmap存放path與pathid。在distinctnode方面也採用了一個hashmap存儲不一樣的node,在方法getDistinctNodeCount()中,只需返回該hashmap的size便可,大大節省了查詢的時間。兩個map設計以下:

private HashMap<Integer, Path> map = new HashMap<>();

map的key爲pathid,value爲Path,這樣能夠節省查找時的時間。在removePath()方法中,須要對map進行遍歷,根據重寫的equals方法找到相應path便可。

private HashMap<Integer, Integer> dismap = new HashMap<>();

dismap的key爲nodeid,value爲該node出現的次數,這樣在刪除一條path時,能夠將該path全部出現的點的次數減一,當次數爲零時,從dismap中移除該點便可。

類圖以下:

複雜度分析:

第二次做業架構設計

本次做業按照規格設計時遇到了許多困惑,在對最短路徑求解時查詢了許多算法,最後使用了florid算法。本次做業並未重構,在第一次做業進行簡單修改就知足了題目要求。

設計以下:

private HashMap<Integer, Path> map = new HashMap<>();
private HashMap<Integer, Integer> dismap = new HashMap<>();

這兩個map沿用第一次的設計,功能也相同。

private int[][] graph = new int[250][250];
private HashMap<Integer, Integer> castmap = new HashMap<>();
private int[] nodecount = new int[250];
private int flag = 0;
private Floyd floyd;
  • graph是一個二維數組,該數組是爲了存儲任意兩點之間是否存在一條邊,用於floyd算法。
  • castmap是考慮到nodeid的數量不會超過250,可是nodeid自己是一個int範圍的數,因此採用了一個castmap,key爲該點的nodeid,value爲映射的值,value的範圍爲[0,250)
  • nodecount數組用來記錄,在[0,250)之間的哪些值已經被映射,下標爲映射的目標值,數組內存放標誌位。在remove時要遍歷dismap,若是該點出現的次數已經爲0,就要刪除這一映射,這樣能夠按照要求將nodeid個數嚴格控制在250之內。
  • flag爲標誌位,每次調用remove或是add方法都須要將flag置一,這樣在每次計算新的floyd最短路徑時,判斷路徑是否有添加或刪除(即flag是否爲1),若是flag爲1則計算新最短路徑,並將flag置0;若是flag爲0,則不計算,採用上一次計算的最短路徑。
  • floyd爲存放Floyd算法的最終結果的一個對象。只有當flag置一時,纔會調用他的構造方法,從新計算新的最短路徑。

類圖設計:

複雜度分析:

第三次做業架構設計

本次做業有點相似曾經學過數據結構課程的最後一次地鐵做業,在最短路徑的求解上依舊採用floyd算法。在討論區學習到了一種算法,根據這種算法結合floyd進行了計算。本次做業最終思路是將問題轉化爲圖內邊的權值問題,而後進行求解。本次做業並未重構,大部份內容沿用第二次做業的代碼,部份內容從MyRailwaySystem類中移入了Floyd類。

算法內容以下:將每條path都變成徹底無向圖,每條path內的每一個點都有直接到達該path內任意一點的距離,同時path內的每條邊都要加上切換path時的額外權值。最終求出的值再減去一次換乘的額外權值,即爲所求。

MyRailwaySystem設計以下:

private HashMap<Integer, Path> map = new HashMap<>();
private int flag = 0;
private int blockNumber;

以上三個數據成員和前兩次做業一直,blocknumber爲連通塊數量,根據並查集求解便可。

private Floyd leastOFtransfer = new Floyd(1);
private Floyd leastOFfear = new Floyd(2);
private Floyd leastOFunpleasant = new Floyd(3);

這三個數據成員即爲本次做業的核心,構造函數傳入構造模式(一個int型變量),以便區分額外權值。

Floyd設計以下:

private static int row = 120;
private int[][] length = new int[row][row];// 任意兩點之間路徑長度
private int addweight;//額外權值
private static HashMap<Path, int[][]> pathHashMap = new HashMap<>();//存儲每條path的徹底無向圖
private static HashMap<Path, int[][]> unpleasantHashMap = new HashMap<>();//單獨存儲unpleasant的徹底無向圖
private static HashMap<Integer, Integer> castmap = new HashMap<>();//映射map
private static int[] nodecount = new int[row];//標記數組
private static HashMap<Integer, Integer> dismap = new HashMap<>();//計算distinctnode點的map
private static int[][] graph = new int[row][row];//存入floyd計算結果
private static int[][] shortestLength = new int[row][row];//最短路徑數組

類圖設計:

複雜度分析:

代碼bug分析

第一次做業:本次做業強測只獲得了80分,緣由是沒考慮到課程組會利用時間卡數據,在不應進行計算的地方反覆進行了計算,因此事件被拖慢了,可是綜合設計是沒有問題的。已經成功合併修復。

第二次做業:本次做業強測45分,由於沒有吸收第一次的教訓,致使本次做業依然犯了不應犯的錯誤,查詢時反覆計算,致使許多點都time_limited。已經成功合併修復。

第三次做業:本次做業強測95分,bug在於數據太大時,我所設定的無限大出如今了數據裏,致使數據錯誤。已經成功合併修復。

規格撰寫和理解的心得體會

規格撰寫本質上體現了從上而下的設計思路,設計好大框架而後一點一點的去構建細節。在學習了JML以後,可以經過已給出的規格實現函數或者類所要求的功能,這是一種很棒的體驗。可是規格自己的學習是較爲困難的,有許多語法上的規定須要記憶,之後仍是要多多練習先寫規格,再寫代碼,這樣不會忘記本身設計的原始意圖,別人讀代碼也會輕鬆不少。

相關文章
相關標籤/搜索