20202312 2020-2021-2《資料結構與面向物件程式設計》課程總結
一、課程內容總結
第一章 緒論
- Java是面向物件程式設計語言。
- 註釋: 應闡明程式編寫目的並描述處理步驟,一般用“//”或“/* */”或“/** */”來標明。
- 識別符號: 由數字、字母、下劃線及美元符號組成(數字不能做開頭)(習慣上定義常數大寫),空白: 空格鍵、Tab鍵、回車換行鍵(單詞與符號的分隔符)。
- 計算機語言發展:機器語言、組合語言、高階語言、第四代語言,Java語言是高階語言。
- 錯誤:1.編譯時錯誤:發生語法錯誤。 2. 執行時錯誤:此時要進行異常處理。 3. 邏輯錯誤:編譯執行沒有問題,但是得到的結果與預期不符。
- 四個基本的開發行為: 1. 建立需求 2. 生成設計 3. 實現設計 4. 測試。
- 基本術語:物件 屬性 方法 類 封裝 繼承 多型。
- 類由class定義,類是物件的藍圖,由一個類定義可以得到多個物件。
第二章 資料和表示式
- print及println方法
- 字串連線:"+"
- 轉義字元:\b:回退鍵 \t:製表符 \n;換行 \r:回車 \ ":雙引號 \ ':單引號 \ \:反斜槓
- 變數宣告:通知程式預留位置並標誌儲存位置名稱
- 變數名=(賦值)變數值
- 常量:final,其值不能改變
- 基本資料型別: 8種(byte,short,int,long,float,double,boolean,char)
- boolean只有true和false
- 算術運算:+、-、*、/、%, 關係運算:、>、>=、<、<=、==、!=, 邏輯運算:&&、||、!
- 運算子優先順序:相同優先順序滿足從左到右的結合律。
- 自增,自減:i++、i--、++i、--i
- 基本型別之間的轉換:三種轉換方法:1. 賦值型別轉換。2. 提升型別轉換。3. 強制型別轉換。同時要注意避免壓縮型別轉換,可能會丟失資訊。
- System.in 與System.out.println
- Scanner類方法:next();nextInt();nextFloat();useDelimiter()等
第三章 類與物件
- new:返回指向新建立物件的引用
- 多個引用變數可以指向同一個物件
- String類方法:compareTo (String str);equals();equalsIgnoreCase()(可以忽略大小寫比較,在使用者進行選擇時常用);length()等。
- Java標準類庫中的類按包來組織。每個類都屬於一個具體的包。呼叫時用import java.util.*;import java.lang.*等。
- Random類:偽隨機數生成器執行復雜的計算產生隨機數
- Math類:方法都是靜態的,可以直接呼叫。
- NumberFormat類:有兩個方法getCurencyInstance和getPercentInstance返回用於格式化數值的物件。getCurencyInstance返回貨幣格式物件,getPercentInstance返回百分比格式物件。
- DecimalFormat類:按慣例使用new運算子來例項化物件。
- 包裝器類:Integer.parselnt( ) Integer.toHexString( )分別是字串轉為int型別,以及將int型別轉為字串型別。
第四章 編寫類
- 類:資料宣告(變數/常量)+方法(函式)。
- 類是物件的抽象\藍圖,而物件是類的具體例項。
- UML類圖:實現、關聯、聚合、組合、繼承。
- 封裝:有些物件要進行封裝,從而防止對該物件的資料進行不適當的訪問。常用的修飾符有public、private。
- 靜態類
1.靜態變數(static):有時也稱類變數,它由類的所有例項共享,在一個物件中修改靜態變數的值,就等於修改了其他所有物件中該靜態變數的值。
2.靜態方法:不需要為了呼叫方法而例項化類的一個物件,只能訪問靜態變數或區域性變數。 - 類關係:依賴,聚合。
第五章 條件判斷與迴圈
- if與if-else語句
- 浮點數的比較:計算兩個差值的絕對值,在與公差進行比較。
- 字元比較:Unicode順序,大小寫字母,數字要聯絡ASCII表中的編碼。
- 對角比較:equals。
- switch語句:switch(){case :break;default:}
- while語句 break跳出迴圈。
- do-while 語句:do{}while();
- for 語句:for( ; ; ),與while等價
第六章 面向物件設計
- 封裝繼承多型。
- extends繼承,程式碼複用,Java只支援單繼承。
- super與this常用於呼叫構造方法。
- 方法過載與重寫:過載:根據引數型別與數量確定初始化方法 重寫:重新編寫父類方法。
- Object類是所有類的父類。
- abstract抽象類達抽象概念,不能用new例項化。
- 抽象類的子類:實現父類的抽象方法變成具體類,不實現父類抽象方法仍要用abstract修飾。
- this關鍵字的使用時呼叫自己類中的方法,主要是為了避免與其他類中相同名稱的方法弄混。
- 多型引用在不同的時候可以指向不同型別的物件。
- 多型引用執行時才將方法呼叫與它的定義繫結在一起。
- 引用變數可以指向宣告繼承於它的任意類的任何物件。
- 介面是一組抽象方法,與抽象類一樣不能被例項化。
- 介面層次:介面可以繼承介面;類可以實現介面,但不能繼承介面。
- Comparable介面:compareTo()
- 和class一樣,介面可以用來宣告物件引用變數。
- 介面引用可以指向實現這個介面的任意類的作何物件。
- 方法的引數可以是多型的。
第七章 異常
- 錯誤和異常(exception)都是物件,代表非正常情況或無效處理。
- 錯誤(Error)不用捕獲。
- 處理異常:在異常發生的地方處理;在程式的其他地方處理。
- 程式中出現異常不捕獲異常,程式會崩潰。
- try-catch 語句: Java中把正常流程放try塊中,錯誤(異常)處理放catch塊中,每個catch 子句處理try塊中可能丟擲的一種特定型別的異常,注意多個catch一定把父類放後面處理, finally:總會執行,用於資源管理。
- finally語句:無論try語句處理情況如何,最後都將執行finally語句。同時,如果有finally子句,則必須跟在catch子句後面。
- 如果沒有在異常發生處捕獲及處理,異常會被傳播給呼叫的方法。
- throw:方法中丟擲Checked Exception,方法宣告中必須有throws。
- Java異常處理是要處理Exception類及其子類。
- 產生RuntimeException的問題在呼叫程式碼。
- I/O異常: 幾乎所有的IO API都可能丟擲異常。
第八章 棧
- 棧是一種線性集合,遵循先進後出(LIFO)原則,
- 棧常見的方法
- push():將元素新增到棧頂
- pop():刪除棧頂元素
- peek():檢視棧頂元素
- isEmpty():判斷棧是否為空
- size():判斷棧中元素的個數
- 使用棧計算字尾表示式:算術表示式有三種寫法,字首,中綴,字尾表示式。用棧來計算字尾表示式時,在從左到右掃描表示式,運算元入棧,遇到操作符則pop兩個數計算後再push。
- 用陣列實現棧的操作,ArrayStack類,用連結串列實現,LinkedStack類。
- 連結串列:與有固定大小的陣列不一樣,連結串列沒有容量上限。
- 連結串列被看成是一個動態結構,它的大小總隨著所儲存的元素個數在變大或變小。
- 連結串列是由具有相同資料型別的元素構成的序列。
- 在使用連結串列時,需要定義結點,通常,我們採用LinearNode類來實現。
第九章 佇列與列表
- 佇列是一個線性集合,它在一端新增元素,在另一端刪除元素————先進先出(FIFO),第一個進入的元素,也就是第一個退出的元素。
- 一般把一端作為佇列的前端(front/head),一端作為末端(rear/tail)。
- 佇列常見方法
- enqueue():向佇列末端新增一個元素
- dequeue():向佇列前端刪除一個元素
- first():檢視佇列前端元素
- isEmpty():判斷佇列是否為空
- size():判斷佇列中元素的個數
- 由於佇列操作會修改集合的兩端,所以我們可以在一端固定一個索引為0的元素。
- 佇列與列表都可用陣列與連結串列來實現。對於佇列,有LinkedQueue與ArrayQueue,對於列表,則有LinkedList與ArrayList。
- 特別的,對於ArrayList類,集合是可變大小的,是按所需來進行空間分配的,這是由列表的特性決定的。因此,這種類在空間管理上十分高效,不會造成浪費。
- 列表裡定義了Iterator方法,該方法是在集合上進行迭代操作,並返回一個Iterator物件。
- 佇列常見方法
- removeFirst():從列表中刪除第一個元素
- removeLast():從列表中刪除最後一個元素
- first():檢視列表第一個元素
- last():檢視列表最後一個元素
- contains:確定列表是否包含某種特定元素
- isEmpty():判斷列表是否為空
- size():判斷列表中元素的個數
- 對有序列表 add:向列表中新增元素
- 對無序列表 addToFront(新增元素到列表頭), AddToRear(新增元素到列表尾), AddAfter(新增元素到某個特定元素之後)。
第十章 選擇與查詢
- 線性查詢:設定哨兵在陣列開頭或結尾,以便提高查詢效率。
- 二分查詢:從中間開始,要求表是有序的,每次比較後可以減少查詢池中的一半元素
- 分塊查詢:先二分查詢,再線性查詢
- 雜湊查詢:直接通過關鍵字找到儲存地址。
- 雜湊查詢
排序
- 選擇排序:分別將每個值放在排好序的最終位置,從而完成一組值的排序。
- 插入排序:將一個具體的值插入到表中已有序的子系列中,從而完成一組值的排序。
- 氣泡排序:重複地比較表中的相鄰元素,如果它們不符合要求則交換他們。
- 快速排序:根據一個任意選定的劃分元素來對錶進行劃分,然後再遞迴地對劃分元素兩邊的欄位進行排序,從而完成對錶的排序。
- 歸併排序:遞迴地對分表,知道每個子表只含有一個元素時為止,然後再將子表按序合併,從而完成對錶的排序。
第十一章 樹
- 樹:節點+邊
- 完全二叉樹(滿二叉樹也是完全二叉樹)
- 樹的遍歷: 先序遍歷、 中序遍歷、 後序遍歷、 層序遍歷
- 二叉樹的實現
- 決策樹:用二叉樹來表示。
- 二叉查詢樹: 查詢、插入、 刪除
- 二叉查詢樹的實現
- 平衡二叉查詢樹
第十二章 堆
- 堆:完全二叉樹(根節點小於左右孩子)
- 堆的實現
- 堆排序
- 優先佇列:具有更高優先順序的項排在前面,具有相同優先順序的項按先進先出的規則排列。
第十三章 圖
- 無向圖:圖中表示邊的頂點對是無序的圖是無向圖,意味著兩點間的連線是雙向的。
- 有向圖:圖中的邊是頂點的有序對的圖為有向圖,意味著有向圖的邊是有方向的邊。
- 帶權圖:圖中每條邊都對應一個權值的圖成為帶權圖,有時也稱為網路。
- 圖遍歷:廣度優先遍歷、 深度優先遍歷
- 無向圖的最小生成樹(Prim演算法或Kruscal演算法)
- 有向圖的拓撲排序 有向圖的最短路徑求解: Dijkstra演算法。
- 圖的實現策略:鄰接表鄰接矩陣
二、作業總結
作業1:面向物件程式設計1,面向物件程式設計2,面向物件程式設計3 ,面向物件程式設計4 ,面向物件程式設計5
- 提交最後三個JUnit測試用例
- 以 TDD的方式研究學習StringBuffer。
- 對設計模式示例進行擴充,體會OCP原則和DIP原則的應用,初步理解設計模式
- 以TDD方法開發一個複數類Complex
- 使用StarUML進行建模
編寫一組程式,要體現一下知識點:
(1)繼承
(2)多型
(3)重寫
(4)過載
(5)目錄建立
(6)檔案建立
(7)位元組流讀寫
(8)字元流讀寫
作業3:實現自己的ArrayList
- 編寫自己的ArrayList類
-
實現增加、刪除、修改、查詢、判斷是否為空、返回list長度等操作。
- 測試
作業4:實驗四 (1)Java Socket程式設計
(2)Java和密碼學
(3)編寫有理數/複數計算器
(4)遠端有理數計算器
(5)遠端複數計算器
作業5: ArrayStack類測試
- 撰寫自己的類;
- 提供StackADT,ArrayStack(框架),實現ArrayStack裡面的剩餘方法;
- 編寫測試類,測試所寫的方法是否正確。
作業6:棧應用-進位制轉換
- 要求輸入一個十進位制數,轉換成任意進位制數並輸出
作業7:最小生成樹測試
- 畫出Prim演算法的最小生成樹的生成過程
- 畫出Kruscal演算法的最小生成樹的生成過程
- 計算最小權值
作業8:最後一次測試
三、實驗報告連結彙總
實驗一:linux基礎與java開發環境
- 基於命令列和IDEA(Intellj IDEA 簡易教程]進行簡單的Java程式編輯、編譯、執行和除錯。
- 練習Linux基本命令;
- 學習Java程式的JDB除錯技能
- 編寫簡單的Java程式。
實驗二:Java基礎(資料/表示式、判定/迴圈語句)
- 編寫簡單的計算器,完成加減乘除模運算。
- 要求從鍵盤輸入兩個數,使用判定語句選擇一種操作,計算結果後輸出,然後使用判定和迴圈語句選擇繼續計算還是退出。
- 編寫測試程式碼,測試驗證。
實驗三:面向物件程式設計
- 初步掌握單元測試和TDD
- 理解並掌握面向物件三要素:封裝、繼承、多型
- 初步掌握UML建模
實驗四:Java Socket程式設計與密碼學
- Java Socket程式設計
- Java和密碼學
- 編寫有理數/複數計算器
- 遠端有理數計算器
- 遠端複數計算器
實驗五和六:線性結構之連結串列
- 連結串列練習,要求實現下列功能:通過鍵盤輸入一些整數,建立一個連結串列;這些數是你學號中依次取出的兩位數。 再加上今天的時間。列印所有連結串列元素, 並輸出元素的總數。
- 連結串列練習,要求實現下列功能:實現節點插入、刪除、輸出操作;繼續你上一個程式, 擴充套件它的功能;從磁碟讀取一個檔案,完成相關操作。
- 連結串列練習,要求實現下列功能:用氣泡排序法或者選擇排序法根據數值大小對連結串列進行排序;
- 在android上實現實驗(1)和(2)
- 在android平臺上實現實驗(3)
實驗七:查詢與排序
- 定義一個Searching和Sorting類,並在類中實現linearSearch,SelectionSort方法,最後完成測試
- 重構你的程式碼
- 參考http://www.cnblogs.com/maybe2030/p/4715035.html ,學習各種查詢演算法並在Searching中補充查詢演算法並測試
- 補充實現課上講過的排序方法:希爾排序,堆排序,二叉樹排序等
- 編寫Android程式對實現各種查詢與排序演算法進行測試
實驗八:樹
- 參考教材完成鏈樹LinkedBinaryTree的實現(getRight,contains,toString,preorder,postorder)
- 基於LinkedBinaryTree,實現基於(中序,先序)序列構造唯一一棵二㕚樹的功能,比如給出中序HDIBEMJNAFCKGL和後序ABDHIEJMNCFGKL,構造出附圖中的樹
- 自己設計並實現一顆決策樹
- 輸入中綴表示式,使用樹將中綴表示式轉換為字尾表示式,並輸出字尾表示式和計算結果
實驗九:圖
- 初始化:根據螢幕提示(例如:輸入1為無向圖,輸入2為有向圖)初始化無向圖和有向圖(可用鄰接矩陣,也可用鄰接表),圖需要自己定義(頂點個數、邊個數,建議先在草稿紙上畫出圖,然後再輸入頂點和邊數)
- 圖的遍歷:完成有向圖和無向圖的遍歷(深度和廣度優先遍歷)
- 完成有向圖的拓撲排序,並輸出拓撲排序序列或者輸出該圖存在環
- 完成無向圖的最小生成樹(Prim演算法或Kruscal演算法均可),並輸出
- 完成有向圖的單源最短路徑求解(迪傑斯特拉演算法)
四、程式碼託管連結
給出statistic.sh的執行結果,
總計:3076行,(截圖如下)
ps:有許多程式碼之前都被自己刪了,就連考試時的程式碼也基本都被自己刪完了,有些dat檔案之類的也沒了,感覺少了好多程式碼,基本idea裡只剩了幾次實驗的。我太難了
課程收穫或不足
1.自己的收穫:java作為自己學習的第二門語言學科,本以為在學習了C後應該會比較簡單,但隨著學習進度的逐漸延伸,慢慢發現java的難度遠超預期,尤其是資料結構,裡面有很多知識點,需要自己去理解,去掌握,最後用程式碼將其實現。在學習java的過程中,最大的收穫就是鍛鍊了自己的抽象思維能力。在學習資料結構相關內容時,裡面的結構很多都是比較抽象的,需要自己課下花大量時間去琢磨,鑽研。儘管過程很痛苦,因為實在是看不懂,但當自己成功的將程式碼實現,自己會感到特別的愜意,那是自己努力了很久,終於把這個問題解決了的感覺。忽然之前難受也就感覺沒啥了。並且,還認識了這麼一位好的老師,答疑解惑耐心負責,我也因此才能在課下練習和課上聽講上有所收穫。最後,自己的自學能力得到了極大的強化,因為實在有很多知識點不瞭解,只能逼著自己去上網找相關解讀,比如CSDN,去B站找相關視訊,課下找相關輔導書,不管如何,自己的自學能力總算有了不小的進步。
2.自己需要改進的地方:學習的效率有時候確實有些低下,就感覺不知道該往哪走,就胡亂看書,搞了半天,還是啥也不會。感覺自己遇到問題可以多向老師或者同學請教,給自己指明方向,這樣自己會節約很多不必要的時間。效率也能提高不少。再就是,相關理性思維能力仍需提高,平時學習中,很多時候自己確實看了想關知識點,但總感覺不是很能完全吃透,很難做到舉一反三這類。最後,就是自己在課下學習的時間應該增加,學習還是得靠自己,光靠上課是不夠的,自己平時花的時間確實少了,以後,要鑽研透,還是得多磨。不管怎樣,路漫漫其修遠兮,吾將上下而求索。