20172328 2018-2019《Java軟件結構與數據結構》第五週學習總結

20172328 2018-2019《Java軟件結構與數據結構》第五週學習總結

概述 Generalization

本週學習了第九章:排序與查找,主要包括線性查找和二分查找算法和幾種排序算法。咱們在軟件開發過程當中要在某一組查找某個特定的元素或要將某一組元素按特定順序排序,因此要學習排序與查找的多種算法。

教材學習內容總結 A summary of textbook

  • 9.1查找
  • 查找:是一個過程,即在某個項目組中尋找某一項指定目標元素,或者肯定該指定目標並不存在。
  • 高效的查找會使該過程所作的比較操做次數最小化。
  • 靜態方法:也稱爲類方法,能夠經過類名來調用,無需實例化該類的對象。 在方法聲明中,經過使用static修飾符就能夠把他聲明爲靜態的。
  • 泛型方法:要建立一個泛型方法,只須要在方法頭的返回類型前插入一個泛型聲明便可:
public static <T extends Comparable<T>> Booolean linearSearch(T[] data,int min,int max,T target);
  • 這樣,就能夠直接經過類名和要用來替換泛型的具體數據類型來調用靜態方法啦。Searching.linearSearch(targetarray,min,max,target)
  • 線性查找法
  • 線性查找法就是從頭開始查找,與每個列表中的元素進行比較,直到找到該目標元素或查找到末尾還沒找到。
  • 如下的方法實現了一個線性查找。該方法返回一個布爾值,如果true,即是找到該元素,不然爲false,表示沒找到。
public static <T>   
 boolean linearSearch(T[] data, int min, int max, T target)
    {
        int index = min;
        boolean found = false;

        while (!found && index <= max) 
        {
            found = data[index].equals(target);
            index++;
        }

        return found;
    }
  • 二分查找法
  • 二分查找是從排序列表(查找池是已排序的)的中間開始查找,而不是從一端或者另外一端的開始的。經過比較,肯定可行候選項就又減小了一半的元素量,以相同的方式繼續查找,直到最後找到目標元素或者再也不存在可行候選項。
  • 二分查找的關鍵在於每次比較都會刪除一半的可行候選項。
  • 如下的方法實現了一個二分查找,其中的最大索引和最小索引定義了用於查找(可行候選項)的數組部分。
public static <T extends Comparable<T>>  
        boolean binarySearch(T[] data, int min, int max, T target)
    {  
        boolean found = false;
        int midpoint = (min + max) / 2;  // determine the midpoint

        if (data[midpoint].compareTo(target) == 0)
            found = true;

        else if (data[midpoint].compareTo(target) > 0)
        {
            if (min <= midpoint - 1)
                found = binarySearch(data, min, midpoint - 1, target);
        }
        
        else if (midpoint + 1 <= max)
            found = binarySearch(data, midpoint + 1, max, target);

        return found;
    }
}
  • 注意:在該算法中,midpoint = (min + max) / 2,當min+max所得數值是基數的時候,會自動轉化成int類型,直接忽略小數部分,也就是肯定中點索引時選擇的是兩個中間值的第一個(小一點的)。
  • 查找算法的比較
  • 對於線性查找和二分查找,最好的情形都是目標元素剛好是咱們考察的第一個元素,最壞的情形也都是目標不在該組中。所以,線性查找的時間複雜度爲O(n),二分查找的時間複雜度爲O(log2(n))。
  • 當n比較大時,即元素特別多的時候,二分查找就會大大提升效率。而當n比較小的時候,線性查找更簡單好調試且不須要排序,所以也在小型問題上經常使用線性查找。
  • 9.2排序
  • 排序:基於某一標準,將某一組項目按照某個規定順序排列。
    • 順序排序:一般使用一對嵌套循環對n個元素進行排序,須要大約n^2次比較。
    • 對數排序:對n個元素進行排序一般大約須要nlog2(n)次比較。
  • 常見的三種順序排序:
    • ①選擇排序、②插入排序、③冒泡排序;
  • 常見的兩種對數排序:
    • ①快速排序、②歸併排序
  • 選擇排序:經過反覆地找到某個最小(或者最大)元素,並把它放置到最後的位置來給元素排序。
  • 插入排序:經過反覆地把某個元素插入到以前已經排序的子列表中,實現元素的排序。
  • 冒泡排序:經過反覆的比較相鄰元素並交換他們,來給元素排序。
  • 快速排序:經過把未排序元素分隔成兩個分區,而後遞歸地給每一個分區排序。
  • 快速排序的平均時間複雜度爲O(nlogn)。在全部平均時間複雜度爲O(nlogn)的算法中,快速排序的平均性能是最好的。
    html

  • 在課本代碼中,須要重點理解Partition方法
while (left < right)
        {
            // search for an element that is > the partition element
            while (left < right && data[left].compareTo(partitionelement) <= 0)
                left++;
            
            // search for an element that is < the partition element
            while (data[right].compareTo(partitionelement) > 0)
                right--;
            
            // swap the elements
            if (left < right)
                swap(data, left, right);
        }
        
        // move the partition element into place
        swap(data, min, right);

兩個內層while循環用於尋找位於錯誤分區的交換元素,第一個循環從左邊掃到右邊,尋找大於分區元素的元素,第二個循環從右邊掃到左邊,尋找小於分區元素的元素,在找到這兩個元素後,將他們互換,該過程會一直持續下去直到左索引和右索引在該列表的「中間」相遇。java

  • 歸併排序:經過遞歸地把列表分半,直到每一個子列表中只剩下一個元素爲止,而後歸併這些子列表。
    git

  • 歸併排序算法穩定,數組須要O(n)的額外空間,鏈表須要O(log(n))的額外空間,時間複雜度爲O(nlog(n)),不須要對數據的隨機讀取。
  • 在課本代碼中,需重點理解merge方法。
  • 基數排序:使用排序密鑰而不是直接地進行比較元素,來實現元素排序。
  • 比較數字大小,咱們是先比位數,若是一個位數比另外一個位數多,那這個數確定更大。若是位數一樣多,就按位數遞減依次往下進行比較,哪一個數在這一位上更大那就中止比較,得出這個在這個位上數更大的數字總體更大的結論。一樣來說咱們也能夠從最小的位開始比較。這就和基數排序原理相通了。
  • 這是一篇介紹的很詳細的博客,你們能夠參考理解桶子法排序原理和實現算法

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

  • 問題1:不明白基數排序RadixSort代碼的循環中爲何循環次數是10次?
for (int digitVal = 0; digitVal <= 9; digitVal++)
            digitQueues[digitVal] = (Queue<Integer>)(new LinkedList<Integer>());
  • 問題1的解決:關鍵就在於Queue<Integer>[] digitQueues = (LinkedList<Integer>[])(new LinkedList[10]);中,最初建立的數組中含有十個隊列,那爲何創造10個隊列呢?經過Debug跟着程序走一遍,我才明白原來這10個隊列是分別保存不一樣的關鍵字取值。而每個數字位上可取0~9的數字,故建立了包含10個隊列的數組。
  • 問題2:仍是在基數排序RadixSort的代碼中,不理解Character.digit方法 digit = Character.digit(temp.charAt(3-position), 10);,隱隱約約以爲Character是一個類,而digit是裏面的靜態方法,從代碼的實現目的來看,應該是獲得特殊位置的元素值。
  • 問題2的解決:經過查詢JavaAPI文檔,獲得以下的解釋。

    其實意思就是將3-position這個位置上的數字值返回。數組

    代碼實現時的問題做答 Exercise

  • 1.在作pp9.2的時候程序寫完後借用Contact的測試類來測試新的gapSort方法,沒有報錯可是排序直接沒有改變。
    數據結構

  • 問題1的解決:實際上是很簡單的錯誤,又檢查了一遍就發現了問題所在,當進行外循環的時候,while語句中應該是知足的條件,而不是跳出循環的條件,在內循環中,只要從比較position-i次便可,這樣全部數字均可以遍歷比較到了。
    性能

  • 2:對pp9.3要求的「在每一個排序法中添加代碼以使得他們可以對總的比較次數和每一算法的總執行時間進行計數」中的計算時間不太瞭解。
  • 問題2的解決:我找到啦java計算代碼段運行時間
    也就是在程序執行前獲取當前系統時間,而後在程序執行完以後再獲取此時的系統時間,二者相減就獲得了該程序的運行時間。
  • 代碼也是很簡潔明瞭の
第一種是以毫秒爲單位計算的。
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");

上週測試活動錯題改正 Correction

  • 1.A circular array implementation of a queue is more efficient than a fixed array implementation of a queue because elements never have to be ___________.(一個用循環數組實現的隊列比起一個用普通數組實現的隊列更高效是由於元素不須要__?)
    A .added(添加)
    B .removed(刪除)
    C .shifted(移動)
    D .initialized(初始化)
  • 問題的改正和理解:因爲隊列操做會修改集合的兩端,所以將一端固定在索引0處要求移動元素,這樣就會使得元素移位產生O(n)的複雜度,而環形數組能夠除去在隊列數組實現中把元素移位的須要。本道題不應錯,也不知道是點錯了仍是當時理解錯題目了學習

    碼雲連接

    代碼量(截圖)

結對及互評Group Estimate

點評模板:

  • 博客中值得學習的或問題:
    • 20172301:這周的博客不只交的早,質量也超級高。課本上的問題有關於public static <T extends Comparable<? super T>>的理解實在到位,並且那個盤裝水果然的妙啊。
    • 20172304:這周的博客有點長哦(褒義的「有點」),很棒!對於pp9.3中的各類排序法的比較次數有本身的深刻探討,可是在博客上的解釋我沒怎麼看懂,大概意思是本身又寫了方法去調用計算?但願以後能一塊兒討論一下。
  • 本週結對學習內容:尚未在一塊兒討論學習, 週五課上應該會有討論的吧!O(∩_∩)O

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

紙上得來終覺淺,絕知此事要躬行。測試

在本週的學習過程當中,其實連得來紙上也花費了一番功夫,尤爲是後面的快速排序、歸併排序和基數排序。.net

大二其實也不算悠閒,天天過的仍是很充實。曾經瞭解過工做外8小時決定人生理論,因此不少時候咱們要去往哪裏也是一點一點時間累積着告訴咱們的。時間安排對一個成年人過重要了,我漸漸意識到本身的生命正由於有侷限纔有不一樣的階段、不一樣的須要、不一樣的安排。

知道我是誰,我要作什麼就好。

原本上面就是這周想說的所有內容了,可是又手欠看了幾篇班裏同窗的博客,真的是太敬佩了。真的有一種個人做業太差了不敢交的感受。就像小時候寫做文寫的不工整不敢交的感受如出一轍。捂臉逃跑~~~

學習進度條Learning List

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 8/8
第二週 621/621 1/2 12/20
第三週 678/1299 1/3 10/30
第四周 2734/4033 1/4 20/50
第五週 1100/5133 1/5 20/70

參考資料Reference

相關文章
相關標籤/搜索