1. 程式人生 > >20172303 2018-2019-1 《程序設計與數據結構》第一周學習總結

20172303 2018-2019-1 《程序設計與數據結構》第一周學習總結

tps 算法分析 加法 增加 練習題 系列 質量體系 找到 可移植性

20172303 2018-2019-1 《程序設計與數據結構》第一周學習總結

教材學習內容總結

第1章 概述

1.軟件工程

  • 定義:一門關於高質量軟件開發的技術和理論的學科。
  • 目標:軟件工程的目標與其他工程學科類似
    • 解決正確性問題————客戶所需實現的需求
    • 按時且在預算之內給出解決方案————預算和給出方案的質量相匹配,學會折中
    • 給出高質量的解決方案————“高質量”由他人定義
    • 以合情合理的方式完成上面的事情————ACM職業道德規範(Code of Ethics and Professional Conduct)

2.軟件質量的特征

  • 在一定程度上講,軟件質量體系在旁觀者的眼中,不同的身份對軟件質量的要求存在差異。同時,一些軟件質量特征之間有時是互斥的,不可能設計出一種軟件符合所有的質量特征。
  • 以每個學校都有的教務管理系統為例來具體闡述一下八個質量特征
    • 正確性:一個教務管理系統要給用戶提供選課、查分等功能,但絕對不可能有食堂點餐這個功能,因為它是一個有關教學相關事務的系統。而如果一個教務管理系統裏不僅沒有查分選課的功能,反而有各種各樣的點餐功能、點外賣功能,那麽這個教務管理系統的正確性很差。
    • 可靠性:在期末有很多同學會進入教務系統查分,如果當進入人數稍微多了一點系統就崩了,那麽說明這個教務系統的可靠性很差。
    • 健壯性:假如出現了上一個特征中出現的情況,學校用了很久很久都沒有修好,等同學們下個學期都快開學了才剛剛修好,那麽這個系統的健壯性就很差。
    • 可用性:一個同學想要查詢一下本學期的課表,結果在教務系統的網站內搜尋了幾個小時最後在一個角落裏找到了查詢課表的入口,那麽這個教務系統的可用性就很差。
    • 可維護性:過了幾年之後有人發現了教務系統存在漏洞,於是有關人員決定對教務系統進行維護修復,但是之前開發這個系統的人都已經退休不幹了,新來的程序員進行修復的時候發現當初寫程序的人寫的極爛無比亂七八糟根本找不到該修復的代碼在哪兒,那麽這個系統的可維護性就很差。
    • 可重用性:學校決定原來的教務系統太老了想重新做一個,但是從零開始過於費時間,就想著能否借用先前的老系統的相關組件來節省時間,但是發現之前的老系統做的太奇葩了而且太過時了真的沒辦法借鑒,那麽原來這個老的教務系統的可重用性就很差。
    • 可移植性:假如一個教務系統用Windows可以打開並且很好的使用,結果有個同學用的MacBook根本打不開教務系統,只好含淚借其他同學的電腦上教務系統,那麽這個教務系統的可移植性就很差。
    • 運行效率:一個同學上教務系統查分,結果查了一天一夜分都沒有出來,那麽這個系統的運行效率就很差。

3.數據結構

  • 定義:計算機儲存、組織數據的方式
  • 上學期關於數據結構的相關學習內容
  • 程序=數據結構+算法

第2章 算法分析

1.算法效率分析

  • 算法效率通常用CPU的使用時間表示。
  • 算法分析是計算機科學的基礎。
  • 算法的效率可以根據該問題的大小和處理步驟數來定義。

2.增長函數

  • 定義:表示問題(n)大小與我們希望最優化的值之間的關系。該函數表示了算法的時間復雜度(CPU的使用時間)空間復雜度(內存空間)
  • 一般我們不需要知道某一算法確切的增長函數,而需要知道算法的漸進復雜度,又稱為算法的階次
    • 漸進復雜度:基於增長函數中的主項,即表達式中增長最快的一項。
    • 階次為增長函數提供了一個上界。除此之外,Ω表示函數的下界,Θ表示函數的上下界。
  • 處理器速度的提高只會給增長函數增加常量

3.大O記法

技術分享圖片

  • 所有具有相同階次的算法,從運行效率的角度來說都是等價的。
  • 需要註意的是,大O記法只關註一個增長函數的主項,這句話看起來簡單,但實際上有些時候很容易讓人產生模糊概念,比如課上留的時間復雜度的計算題的第四個:
void fun (int n){
   int i=0;
   while(i*i*i<=n)
       i++;
}
  • 有些同學通過將n帶入不同常數計算後認為這段代碼的時間復雜度是O(n的立方根+1),就是混淆了階次的概念,這段代碼的增長函數是n的立方根+1,而它的時間復雜度則是O(n的立方根)。

4.增長函數的比較

  • 如果能保證問題(n)很小,那麽使用何種算法是無關緊要的。
    技術分享圖片
  • 但是當問題(n)很大時,各種算法之間的差距就會很明顯。
    技術分享圖片

5.時間復雜度分析

  • 步驟:首先確定循環體的階n,然後乘以循環次數。
  • 規則
    • 加法規則:T(n,m) = T1(n) + T2(n) = O (max ( f(n), g(m) )
    • 乘法規則:T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))
    • 一個特例(問題規模為常量的時間復雜度):在大O表示法裏面有一個特例,如果T1(n) = O(c), c是一個與n無關的任意常數,T2(n) = O ( f(n) ) 則有T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) )
  • 循環運行的復雜度分析
for(int count = 0; count < n; count++)
{
    //復雜度為O(1)的步驟系列
}
//復雜度為O(1×n)即O(n)
  • 嵌套循環的復雜度分析
for(int count = 0; count < n; count++)
{
    for(int count2 = 0; count2 < n; count2++)
    {
        //復雜度為O(1)的步驟系列
    }
}
//復雜度為O(1×n×n)即O(n^2)
  • 方法調用的復雜符分析
for(int count = 0; count < n; count++)
{
    printsum(count);
}

該代碼段的復雜度要根據printsum方法的復雜度來確定,假如printsum方法為

public void printsum(int count)
{
    int sum = 0;
    for (int I = 1; I < count; I++)
        sum += I;
    System.out.println(sum);
}

那麽上面的代碼段的復雜度就為O(n^2)。而假如printsum方法為

public void printsum(int count)
{
    int sum = 0;
    sum = count * (count + 1)/2;
    System.out,println(sum);
}

那麽代碼段的復雜度為O(n)。

教材學習中的問題和解決過程

  • 問題1:可靠性和健壯性都與軟件的故障相關,那麽它們之間的區別和聯系究竟在哪兒?
  • 問題1解決方案:書上的第九頁有這麽一段話

    可靠性關註的是軟件系統發生故障的頻率以及在什麽環境下發生故障,而健壯性關註的是軟件系統出現故障時會發生什麽。

  • 我的理解是可靠性關註的是故障發生之前的相關內容,而健壯性關註的是故障發生之後的相關內容。

教材課後練習題

EX 2.1 下列增長函數的階次是多少?

  • a.10n^2+100n+1000
  • 解答:階次為O(n^2)
  • b.10n^3-7
  • 解答:階次為O(n^3)
  • c.2^n + 100n^3
  • 解答:階次為O(2^n)
  • d.n^2×logn
  • 解答:階次為O(n^2×logn)

2.4 請確定下面代碼段的增長函數和階次

for(int count = 0 ; count < n ; count++)
    for(int count2 = 0 ; count2 < n ; count2 = count2 + 2)
        {
            System.out.println(count,count2);
        }
}
  • 解答:增長函數為f(n)=n^2/2, 階次為O(n^2)。
for(int count = 0 ; count < n ; count++)//循環次數為n,復雜度為O(n^2)
    for(int count2 = 0 ; count2 < n ; count2 = count2 + 2)//循環次數為n/2,復雜度為O(n)
        {
            System.out.println(count,count2);//復雜度為O(1)
        }
}

為了確保正確性,我寫了一個程序來實際測試了一下,發現的確內層的循環次數為n/2,外層的循環次數為n,證明增長函數和階次是對的。
技術分享圖片

2.5 請確定下面代碼段的增長函數和階次

for(int count = 0 ; count < n ; count++)
    for(int count2 = 1 ; count2 < n ; count2 = count2 * 2)
        {
            System.out.println(count,count2);
        }
}
  • 解答:增長函數為f(n)=n×log2n,階次為O(n×log2n)。
for(int count = 0 ; count < n ; count++)//循環次數為n,復雜度為O(n×log2n)
    for(int count2 = 1 ; count2 < n ; count2 = count2 * 2)//循環次數為log2n,復雜度為O(log2n)
        {
            System.out.println(count,count2);//復雜度為O(1)
        }
}

再拿程序來測試一下:
技術分享圖片
技術分享圖片

結對及互評

  • 本周結對學習情況
    • 20172322
    • 結對學習內容:本周內容相對簡單,且時間比較緊迫,課本內容都是各自自行學習的。
  • 博客中值得學習的或問題:
    • 優點:雖然很殘忍.....但是感覺....沒有優點....
    • 問題:內容有些過於簡單,感覺很多東西都沒有自己深入的理解。

其他(感悟、思考等,可選)

新的一個學期又開始了,很慚愧上個學期期末靠著背單詞和寫博客拿了一個不錯的分數。本學期的學習目標是希望自己的動手能力能夠有所加強,不會的東西要多去試一試,不要只局限於知識,一定要學會應用。
技術分享圖片

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一周 10/10 1/1 10/10
  • 計劃學習時間:5小時

  • 實際學習時間:10小時

  • 改進情況:本來感覺這周東西不多,老師還在課上都講過了,沒想到還是廢了不少時間。本來嘗試使用markdown語法去編輯公式,結果發現用不了,好像博客裏給的方法只能在CSDN裏面用o(╥﹏╥)o

參考資料

  • 算法時間復雜度的計算
  • markdown編輯數學公式

20172303 2018-2019-1 《程序設計與數據結構》第一周學習總結