20172314 2018-2019-1《程序設計與數據結構》第五週學習總結

教材學習內容總結

查找

  • 查找:在某個項目組(查找池)中尋找某一指定目標元素,或者肯定該指定目標並不存在。
  • 目標是高效的完成查找,使得爲了尋找目標所作的比較操做次數最小化,且查找池中項目的數目就定義了問題的大小。
  • 在查找對象的過程當中須要進行對象之間的比較,咱們用Searching類實現Comparable接口,但使用查找排序方法時必須實例化Searching類,爲了解決這個問題須要把全部方法聲明爲靜態或泛型的。靜態方法(類方法)經過使用static修飾符聲明,調用靜態方法不用實例化該類的一個對象。靜態方法不是做用於具體的對象中,所以他們不能引用實例變量,但能夠引用靜態變量,由於靜態變量的存在於具體的對象無關。main方法必須用static修飾符修飾,只能方法靜態或局部變量。
  • 建立一個泛型方法:在方法頭的返回類型前插入一個泛型聲明便可:html

    public static <T extends Comparable< T>> boolean linearSearch (T[] data, int min, int max, T target)

    這樣含有返回類型和參數類型的方法就可使用泛型參數了。需注意,泛型聲明需位於返回類型以前,這樣泛型纔可做爲返回類型的一部分。建立泛型方法以後就不用在每次使用Searching類的方法以後都去實例化該類,只須要用類名和要用來替換泛型的具體數據類型,就能夠調用靜態方法。java

  • 兩種常見的查找方式
    • 線性查找法
      • 從列表頭開始依次比較每個值,直到找到目標元素,最終找到目標元素或者到達列表尾得出不存在目標元素。
    • 二分查找法
      • 使用二分查找法的前提是查找池中的項目組是已經排好序的。
      • 二分查找法是從排序列表的中間開始查找,若是沒有找到,根據中間數值與目標數值的大小比較,從前一半或後一半接着查找,每次比較操做以後,將消減一半查找池,剩下的一半查找池將表示可行候選項。
    • 查找算法中的比較
      • 二分查找的優點:git

        線性查找的複雜度爲O(n),二分查找的複雜度是對數級的,爲O(log2n),這使得他對於大型查找池很是有效率。
      • 線性查找的優點:算法

        線性查找比二分查找簡單,編程調試容易,而且線性查找無需花費額外成原本排序該查找列表。
      • 對於兩者的選擇須要在將查找池保持爲排序狀態和提升查找效率的努力之間權衡。編程

排序

  • 排序:基於某一標準,基於某個規定順序將某一組項目排序。
  • 基於效率排序算法
    • 順序排序:使用一對嵌套循環對n個元素排序,大約須要n^2次比較。
    • 對數排序:對n個元素進行排序一般須要大約nlog2n次比較。
    • n較小時,兩種算法之間幾乎不存在實際差異。
  • 選擇排序:
    • 算法經過反覆地將某一特定值放到它在列表中的最終已排序位置,從而完成對某一列值的排序。
    • 通常爲:掃描整個列表找出最小值,將這個值與該列表第一個位置處的值交換。而後掃描剩下的找出最小的與第二個位置的數交換,以此類推,這一過程結束時就排好序了。
  • 插入排序法
    • 算法經過反覆將某一特定值插入到該列表某個已排序的子集中來完成對列表值的排序。
    • 對頭兩個值依據其相對大小進行排序,第三個值插入到前兩個之間的恰當位置,以此類推,該插入過程須要對數組中的其餘元素移位。
  • 冒泡排序法
    • 使用了兩個嵌套循環的順序排序算法。他經過反覆重複比較列表中的相鄰元素,並在他們彼此不符順序時將他們互換來完成對值的排序。
    • 掃描列表比較臨近的元素,若是他們不是按相對順序排序則互換,把最大值,冒泡到列表最後一個值,而後再次掃描列表,冒泡出倒數第二個值。直至全部元素都被冒泡到正確位置。
  • 快速排序法
    • 經過使用一個任意選定的分區元素將該列表分區,而後對分區元素的任一邊的子列表進行遞歸排序。
    • 通常策略:先選擇一個列表元素做爲分區元素,分隔列表,使得小於分區元素的全部元素位於該元素的左邊,全部大於該分區元素的位於右邊。而後對這兩個分區進行遞歸式排序。
  • 歸併排序法
    • 是一種遞歸算法,將列表遞歸式分紅兩半,直至每一子列表中都含有一個元素,而後將這些子列表按順序重組。


  • 基數排序法
    • 基於隊列處理的。對三位數的排序,首先要對個位、十位、百位數字依次進行排序,
    • 關鍵字中的每一個數字/字符的每種可能值,都會建立一個單獨的隊列,隊列的數目稱爲基數。例如對12 34 32 進行排序,這些兩位數的每一個數字位都取1~4之間的數,就意味着須要4個隊列,基數爲4。

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

  • 問題一:在看課本的時候,對於基數排序法不怎麼理解,沒能理解前兩次遍歷的意義,我以爲直接進行第三次遍歷就好了。並且爲何要先排個位數最後是百位數,這樣作的緣由是什麼。
  • 問題一解決:結合圖示數組

    發現因爲數字被儲存在隊列中,因此進隊列出隊列的順序是很重要的,先進先出,對於圖中的例子來講,第一次遍歷對個位數進行排序,出隊列時按照數字0~5分別從本身的隊列中出來,對於十位的第四個數的那個隊列來講,第一次遍歷的價值就體現出來,145 143 442 341按順序從右到左先進入隊列,到第三次遍歷時,對於數字1的隊列,143比145先出來進入到新隊列,因爲在第一次遍歷時已經對個位進行了排序,143比145小,在百位上已經完成了排序。因此說,先比較個位而後十位百位,能夠巧妙的按從小到大的順序排序。學習

  • 問題二:在書上基數排序法中看到代碼測試

    if(temp.length()>position){
                    digit = Character.digit(temp.charAt(temp.length()-1 - position), 10);//十進制
                }else{
                    digit = Character.digit('0', 10);//十進制
                }

    不知道方法digit = Character.digit('0', 10);是什麼意思。同時也不是很理解基數排序代碼的含義。.net

  • 問題二解決:經過查找資料發現java.lang.Character.digit()方法
    3d

    意思是輸出ch的indax進製表示。
    因此說課本代碼的意思是輸出temp.charAt(temp.length()-1 - position)的十進制表示。對代碼的理解爲:

    for (int scan = 0; scan < list.length; scan++) {
               //scan查找每一個數字
               temp = String.valueOf(list[scan]);// /轉化爲字符串
               if(temp.length()>position){
                   //例如三位數在對百位排序,就把對應位次的字符換爲十進制的數字
                   digit = Character.digit(temp.charAt(temp.length()-1 - position), 10);//十進制
               }else{
                   //例如對於兩位數在對百位排序,就在高位添加0,對數字不影響
                   digit = Character.digit('0', 10);//十進制
               }
               //對本次遍歷的數排序。例如第一次遍歷對個位數進行排序,則按照個位數排序的結果存入隊列中
               digitQueues[digit].add(new Integer(list[scan]));// 隊列
           }

代碼調試中的問題和解決過程

  • 問題一:運行出現錯誤

  • 問題一解決: for循環的條件必須知足在間隔固定數後的也比position小,因此就會產生出界,須要添加條件scan + i <= position; scan++),但因爲i是大於1的,因此知足scan + i <= position,必定有scan <= position,因此改成for (scan = 0; scan + i <= position; scan++)
  • 問題二:如何計算代碼運行時間?
  • 問題二解決:從網上找到了兩種辦法
    • 第一種(以毫秒爲單位):

      long startTime = System.currentTimeMillis(); //獲取開始時間

      doSomething(); //測試的代碼段

      long endTime = System.currentTimeMillis(); //獲取結束時間

      System.out.println("程序運行時間:" + (endTime - startTime) + "ms"); //輸出程序運行時間
    • 第二種(以納秒爲單位):

      long startTime=System.nanoTime(); //獲取開始時間

      doSomeThing(); //測試的代碼段

      long endTime=System.nanoTime(); //獲取結束時間

      System.out.println("程序運行時間: "+(endTime-startTime)+"ns");

  • 問題三:出現屢次輸出

    一開始只是在每一個方法的開始和結尾計時,輸出結束時間-開始時間的差值,運行結果卻發現對於5種排序方法居然有17個輸出。而且有些比較次數爲0.
  • 問題三解決:

    對於插入排序法來講,因爲count2在循環內部,輸出的count2直接是聲明變量的值0,而輸出比預計多猜想是由於迭代時形成累計輸出,而後添加了每一個方法的輸出語句,證實猜想是正確的

    而後發現插入排序的次數一直是0

    後來發現須要在while循環外面再加一次計數。

代碼託管

上週考試錯題總結

  • 錯題一:

  • 錯題一解析:無序列表的元素按照特殊順序放置,這種順序與元素自己無關,列表的使用者決定元素的順序。
  • 錯題二:

  • 錯題二解析:Java Collections API包含三個索引列表的實現,add(int index,E element),remove(int index),set(int index,E element)

結對及互評

  • 20172305譚鑫譚鑫的博客對於問題的記錄一直以來都很詳細,不只記錄了他的解決辦法,還有他的思考過程,以及擴充知識,他可以發現問題並能主動學習的精神值得學習。
  • 20172323王禹涵王禹涵的博客最明顯的有點就是重點的彩色標識和手寫問題解釋,能夠看出來他有認真的學習總結,同時他的教材內容總結部分也是本身的理解,很用心。

其餘

此次的做業小組配合不少,在作PP9.3時,咱們三我的的比較次數都不徹底同樣,最後在羣裏一個方法一個方法測試,討論正確的比較計數。感受小組合做的做用是很是大的!

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 8/8
第二週 1163/1163 1/2 15/23
第三週 774/1937 1/3 12/50
第四周 3596/5569 2/5 12/62
第五週 3329/8898 2/7 12/74

參考:

相關文章
相關標籤/搜索