2017-2018-1 學習總結目錄: 1 2 3 5 6 7 9 10 11 12
html
- 0. 教材學習內容總結
- 0.1 查找
- 0.2 排序
- 0.3 分析查找與排序算法
- 1. 教材學習中的問題和解決過程
- 1.1 快速排序示例的理解
- 1.2 算法複雜度練習
- 2. 代碼調試中的問題和解決過程
- 2.1 數組中的字符串元素排序
查找是在數據項中找到指定目標元素或是肯定目標不存在的過程。git
查找池中找到目標須要的比較次數會隨着數據項的增長而增長;
查找算法做用於 Comparable (多態)對象中的數組(compareTo 方法比較元素)。算法
public static Comparable binarySearch (Comparable[] data, Comparable target){ Comparable result = null; int first = 0, last = data.length - 1,mid; //查找範圍 while(result == null && first <=last){ mid = (first + last)/2; //中間位置比較元素 if (data[mid].compareTo(target) == 0) result = data[mid]; //查找成功 else if(data[mid].compareTo(target) > 0) last = mid - 1; //範圍縮小到前半段 else first = mid + 1; //範圍縮小到後半段 } return result; }
【補充】二分查找算法主要步驟概括以下:(假設是有序列表)
(1)定義初值:first = 0, last = length - 1
;
(2)若是first ≤ last
,循環執行如下步驟:
①mid = (first + last)/2
;
② 若是 target 與 data[mid] 的關鍵字值相等,則查找成功,返回 mid 值,不然繼續執行;
③ 若是 target 小於 data[mid] 的關鍵字值,那麼last = mid - 1
,不然first = mid + 1
。
(3)若是first > last
,查找失敗,返回 null。數組
---
排序:按照某種標準將一列數據項次序重排;
依據:關鍵字(字母、數字等);
順序:遞增、遞減、非遞增、非遞減。數據結構
public static void selectionSort(Comparable[] data) { int min; for(int index = 0 ; index < data.length - 1; index++) // 控制存儲位置 { min = index; for(int scan = index + 1;scan < data.length; scan++) // 查找餘下數據 if (data[scan].compareTo(data[min]) < 0) // 查找最小值 min = scan; swap(data,min,index); // 交換賦值 } }
交換方法:性能
private static void swap(Comparable[] data,int index1,int index2){ Comparable temp = data[index1]; //引入一個臨時變量 data[index1] = data[index2]; data[index2] = temp; }
示例:
學習
for(從第二個數據開始對全部數據循環處理) { while (第i個數據小於它以前的第i-1個數據) { 將第i個數據複製到一個空閒空間臨時存儲,這個空間爲「哨兵」 在前i-1個數據中尋找合適的位置,將從該位置開始的元素所有後移 將哨兵數據插入到合適位置 } }
public static void insertionSort (Comparable[] data) { for (int index = 1; index < data.length; index++) { Comparable key = data[index]; int position = index; // 哨兵臨時存儲 while (position > 0 && data[position-1].compareTo(key) > 0) { data[position] = data[position-1]; //位置所有後移 position--; } data[position] = key; //合適位置 } }
示例:
測試
希爾排序:把一個長序列分割爲若干個短序列,直接插入排序。
示例:
優化
public static void bubbleSort (Comparable[] data) { int position, scan; for (position = data.length - 1; position >= 0; position--) { for (scan = 0; scan <= position - 1; scan++) if (data[scan].compareTo(data[scan+1]) > 0) swap (data, scan, scan+1); //逆序交換 } }
示例:
ui
public static void quickSort (Comparable[] data, int min, int max) { int pivot; if (min < max) { pivot = partition (data, min, max); // make partitions(定義樞軸) quickSort(data, min, pivot-1); // sort left partition quickSort(data, pivot+1, max); // sort right partition } }
劃分並排序:
private static int partition (Comparable[] data, int min, int max) { // Use first element as the partition value Comparable partitionValue = data[min]; int left = min; int right = max; while (left < right) { // Search for an element that is > the partition element while (data[left].compareTo(partitionValue) <= 0 && left < right) left++; // Search for an element that is < the partitionelement while (data[right].compareTo(partitionValue) > 0) right--; if (left < right) swap(data, left, right); } // Move the partition element to its final position swap (data, min, right); return right; }
示例:
public static void mergeSort (Comparable[] data, int min, int max) { if (min < max) { int mid = (min + max) / 2; mergeSort (data, min, mid); mergeSort (data, mid+1, max); merge (data, min, mid, max); } }
歸併算法中關鍵代碼:
int first1 = first, last1 = mid; // endpoints of first subarray int first2 = mid+1, last2 = last; // endpoints of second subarray int index = first1; // next index open in temp array // Copy smaller item from each subarray into temp until one // of the subarrays is exhausted while (first1 <= last1 && first2 <= last2) { if (data[first1].compareTo(data[first2]) < 0) { temp[index] = data[first1]; first1++; } else { temp[index] = data[first2]; first2++; } index++; }
以後檢查各個序列中的元素是否用盡,最後將有序數據複製回原數組。
示例:
分配排序:用額外空間節省時間。(桶排序、基數排序)
示例:
堆排序:堆積排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆是一個近似徹底二叉樹的結構,並同時知足堆性質:即子結點的鍵值或索引老是小於(或者大於)它的父結點。
示例:
考慮最差情形
查找算法:二分查找高效(對數階)
排序算法:性能比較
排序方法 | 平均時間 | 最壞狀況 | 輔助存儲 |
---|---|---|---|
冒泡排序 | O(\(n^2\)) | O(\(n^2\)) | O(1) |
選擇排序 | O(\(n^2\)) | O(\(n^2\)) | O(1) |
希爾排序 | O(nlogn) | O(nlogn) | O(1) |
快速排序 | O(nlogn) | O(\(n^2\)) | O(logn) |
堆排序 | O(nlogn) | O(nlogn) | O(1) |
歸併排序 | O(nlogn) | O(nlogn) | O(n) |
插入排序 | O(\(n^2\)) | O(\(n^2\)) | O(1) |
桶排序 | O(n) | O(\(n^2\)) | O(n) |
基數排序 | O(d(n+k)) | O(d(n+k)) | O(d(kd)) |
【注】表中n是排序元素個數,d個關鍵字,關鍵碼的取值範圍爲k
【問題1】:在看本章內容的PPT時,快速排序有一個示例沒看懂,只看圖的話,我以爲實線圈中的數和加粗的虛線圈中的數的位置變更沒有什麼規律,因此不太理解快速排序的執行順序。
解決方案 :在仔細閱讀了相關內容以後,我發現實線圈中的數和加粗的虛線圈中的數的位置變更規律、比較順序並非受到同類線圈的影響,在選好樞軸之後,就開始首尾比較元素,以49爲樞軸,左右依次比較,順序就跳過一次,直到縮減到中間位置,便實現了劃分序列。我原來是被不一樣的線圈中的數迷惑了,才弄錯了執行次序。
【注】樞軸是一個數。
void fun3(int n) { int i=0,s=0; while (s<=n) { i++; s=s+i; } }
【問題】:在看教材代碼程序13.4時,不理解將姓氏和名字交換過來以後怎麼對數組中的字符串元素排序?
解決方案 :在IDEA中使用debug單步調試,我發現這裏的關鍵字是按照字母的順序排列,從而返回一個正整數,負整數或者0。如圖所示:這裏的scan索引是D開頭的姓氏,而min索引是F開頭的姓氏,使用compareTo比較時(ASCII碼錶中),至關於將字母當成數字相減,因此這裏得出的是負整數-2,小於0,因此從新賦值,即最小索引對應的值。
本週課下測試還未給出錯題和解析:
double fun(double y,double x,int n) { y=x; while (n>1) { y=y*x; n--; } return y; }
【正解】計算\(x^n\);O(n)
【理解】當時由於循環前將x的值賦給了y,因此我有點糾結究竟是計算\(x^n\)仍是\(y^n\),最後寫成\(y^n\)。仔細一想,在循環前的y是否賦值與循環內的x沒有關係,即便循環以外y賦值爲x,循環內仍然是x,若是將循環內的y理解爲x那麼y則是無規律增加的,因此這裏是計算\(x^n\),至於O(n),我居然忘記了加大O符號(¬_¬)。
void fun3(int n) { int i=0,s=0; while (s<=n) { i++; s=s+i; } }
【正解】O(\(\sqrt{n}\))
【理解】之因此作錯是由於當時沒有仔細考慮while循環的執行次數,利用數學中的等差數列公式,能夠最後獲得 \(\frac{T(n)*[T(n) + 1]}{2}\),可簡化爲\(T^2\)(n),而這個值又小於等於n,因此T(n) ≤ \(\sqrt{n}\),即時間複雜度爲O(\(\sqrt{n}\))。
本週狀態通常,比前兩週稍差一些,有點匆忙,可是每當空閒時有有些缺乏動力,本週課堂測試作得也很差,能作對的2分題沒有得分,說明前一章的掌握狀況有些死板。對於這周的學習內容,我明顯感受到難度在逐漸上升。這周的活動略多,老是忽然來一個通知,有時會影響一天的計劃,可是也不能由於事多就把主要精力大量分散。下週繼續保持狀態,求穩不求快。
【附1】教材及考試題中涉及到的英語:
Chinese | English | Chinese | English |
---|---|---|---|
泛型 | generic | 劃分元素 | partition element |
線性查找 | linear search | 樞軸點 | pivot point |
二分查找 | binary search | 優化 | optimize |
插入排序 | insertion sort | 子表 | sublist(s) |
歸併排序 | merge sort | 子集 | subset |
排除 | eliminate | 指定的 | designated |
【附2】本週小組博客:團隊學習:《構建之法》
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 234/234 | 1/28 | 14/14 | 瞭解算法效率、大O符號等理論內容 |
第二週 | 255/489 | 1/29 | 12/26 | 瞭解敏捷的團隊、泛型的使用 |
第三週 | 436/925 | 2/31 | 10/36 | 瞭解一些查找和排序的算法 |
計劃學習時間:14小時
實際學習時間:10小時
有效學習時間:4小時
改進狀況:學習時間有些降低,本週建立小組博客反覆試驗模板花費了一些沒必要要的時間,在代碼上明顯感受有些亂,下週打算把課本上的內容再過一遍。