本單元主要學習根據課程組提供的介面中的jml規格,實現自己的方法。 jml是一種形式化的、面向j**a的行為介面規格語言,起初會比較陌生,但是在熟悉後還是比較直白易懂的,而且比較直接也非常詳細地給出了思路,當然了,本次作業中有許多處的容器和資料結構是需要自己設計和優化的。這也是三次作業主要的工作量。不過總體而言,工作量相比前兩單元還是少了很多。
本單元總體上需要設計的地方不如求導單元和電梯單元多,我的設計流程如下
所以設計也就集中在演算法處。
本次的測試,最開始還是自己粗略檢查是否完備地實現了jml所要求的各種瑣碎的細節。當然了,這個層次的檢查也只是可以糾正一些簡單的手誤或者低階錯誤。
進一步的測試則是在跑過測評機的大量資料後,與同學對拍實現的。由於作業中社交系統的功能十分複雜,且互相間的承接也比較重要,比如一定量的人和關係是其他一切功能的基礎,所以純隨機出的測試樣例,並沒有辦法直擊要害,也出現了多次對拍後仍然暴斃的慘狀。所以之後的資料增加了對邊界情況的考慮和對效能的考察,也起到了不錯的效果。在對拍中,參與的幾個朋友都出現了不同程度的問題。
因為事前看了一些部落格,所以person類的熟人和network裡的人直接選擇無腦莽hashmap,network裡還加了乙個hashmap,進行演算法中使用的並查集的祖先的儲存。
本次需要考慮的效能問題應該就是iscircle和queryblocksum這兩個方法。
public int fd(int x)int ans = fd(fdlist.get(x));
fdlist.replace(x, ans);
return ans;
}
本次作業在最初弱測有個點卡了一會,後來看群裡同學的討論解決了。在加入新人時,沒有設定其連通自己,導致後續出現了別的問題。給我的教訓就是,在本單元根據jml實現各個方法時,很容易產生疏離感,讓你感覺自己只在寫手頭上這個方法,而忘卻了這個社交系統的整體性和各部分間的聯絡。就像高中刷的《小題狂做》,一上頭就變成《小題狂錯》!所以在寫的時候還是要時刻提醒自己在寫乙個社交系統,不忘初心。
強測和互測均未出現bug。
五一旅遊了所以沒有hack,房裡出現的bug就是有同學的iscircle複雜度過高導致了ctle。
第二次作業新增了group類和message類,相關的資料還是使用hashmap儲存。和某個同學交流的時候獲知他某處使用了鍊錶?思考後並沒有覺得**使用鍊錶比較合適。
本次需要考慮的問題是對group中人員的valuesum、agemean、agevar的相關計算,其中valuesum是o()的複雜度,所以極易ctle。
解決方式就是進行相關值的快取,並實現相應的維護。
private int agesum;因為jml規格更新的問題,最初出現了1111人之後繼續新增的情況,不過更新了強測資料之後就沒問題了。讀jml還是要耐下性子,不能遺漏。private int age2sum;
public void addperson(person person)
public void delperson(person person)
其餘就是最開始沒有快取相應資料,出現了ctle,快取後修復了此bug。
hack部分根據評測機隨機出的大量資料,hack出了部分同學的ctle。這部分其他確實很難出問題,只有複雜度這部分你可以做文章。
新增了emoji message及其熱度的儲存,我使用了兩個hashmap,現在看來其實是冗餘的,兩個完全可以合併為乙個,還可以簡化部分編碼,所以也沒必要無腦服從jml。
本次的問題集中在sendindirectmessage這一方法。我選擇了堆優化的迪傑斯特拉演算法,新建edge類,屬性為to和cost,表示到指定人的value。
public int dijkstra(int id1, int id2)在寫的過程中還遇到了乙個問題,我最初使用了arraylist來儲存演算法中的幾個資料,直接通過id來對映,後來發現,id的範圍是無法限制的,所以使用arraylist一定是不可行的,遂換為hashmap。更換容器後,對演算法中的部分細節進行了修改。if (vis.containskey(u))
vis.put(u, 1);
for (integer key:((myperson)getperson(u)).getacquaintance().keyset()) else if (dis.get(next) > dis.get(u) + cost) }}
}return dis.get(id2);
}
第乙個bug是在遍歷hashmap過程中進行了刪除,更換了removeif的寫法之後修復了bug。這個bug也讓自己對迭代器及hashmap的一些基礎知識有了進一步的理解和認識。
第二個就是引入emojiid之後,出現了兩個id混淆的情況,這就是個人寫**時是否足夠細緻的問題。
強測中t了乙個點,因為資料中各種指令都有,所以我也不清楚到底是哪部分的問題。自己的猜測是valuesum的歷史遺留問題,我採用的優化差不多是個偽優化,即不遍歷整個people的hashmap,只遍歷person的熟人,如果給person和people裡的所有人加上關係,這個優化等於是個無效優化。其他就是可能自己的迪傑斯特拉還有需要優化的地方。
互測中未被hack,閱讀房友的**後發現正確性沒有問題,要考慮複雜度的話,全是堆優化的迪傑斯特拉,也不知道咋下手,就沒有再進一步hack。
不可否認,jml具有其高效性,能清晰地提出要求,劃清邊界,但是在本單元學習之後,也只是培養了根據jml實現功能的能力,要自己動手寫的話可能是亞托謝特。
同時,本單元每次作業的幾個主要任務的jml,長度還是有點噁心的,加上藏在注釋裡灰溜溜一片,看上去就不想讀。
不過一行一行理清頭緒,分塊後耐心思考,也還是能比較輕鬆地搞清楚其功能的。看多了之後也能總結出為了實現某種功能的jml的大致套路。
同時,不能讓jml成為自己的桎梏,還是要結合自己的思考,如果確信,要敢於邁出jml。
本單元的評測相比較前面兩單元還是比較豐富的,因為boygg搞了個測評機來對拍(lbynb!)。
這樣還是比較高效的,對拍過程確實找出了每個人各個地方出現的奇怪bug。同時,根據對拍出的異常結果迅速定位bug並解決的能力也有提公升。
一是j**a基礎。當初寒假的預習作業讓人產生了自己j**a行了的錯覺,其實不然,很多基礎部分都模稜兩可。就像第三次作業的遍歷hashmap後刪除的問題,也是在細讀討論區加上自行搜尋後才搞清了其中的原理。所以這部分還是不能忽略的。
二是演算法基礎。還沒有系統學習演算法,資料結構說實話也記憶模糊。本單元使用的演算法,基本是只記得大概原理,具體實現還是現學。
當然了,這兩部分想要提高當然不是一日之功,能做的就是從現在開始腳踏實地,慢慢積累。
BUAA OO 第三單元總結
一句話概括一下就是 先理解再動手,先實現再優化。首先肯定是要仔細閱讀所提供的jml規格,充分理解規格的作用和其需要完成的任務,在動手之前也先想好要用到什麼內容 選用什麼容器啦,要用什麼資料啦,需不需要修改原本的資料等等 這一點無可厚非。第二步就是先試著動動手,暫不考慮效能以及該規格與原有內容之間的內...
BUAA OO 第三單元總結
本次作業中的規格實現我採取了巨集觀到具體 增量修改 改不了就重構 的策略,大致進行以下幾個步驟。1.首先瀏覽整體某個類中所儲存的資料和需要實現的方法,梳理方法的大致含義以及方法與資料儲存之間的關係。2.找到幾個比較複雜 一般是jml很長 的方法,現根據規格給出的方法大體實現一遍,計算複雜度。3.若複...
BUAA OO 第三單元作業總結
本單元作業由於設計架構已經基本規定好,只需要實現部分介面的功能即可,所以歷次作業的實現幾乎相同,都遵循以下幾個步驟 閱讀指導書,先大體梳理一遍需要實現的是哪些部分 閱讀jml整體規格,關注當前介面對應的類需要維護哪些屬性以及該類的規格大小,並大體閱讀一下有哪些方法以選擇適當的容器 細讀jml規格,先...