本章出現了全書第乙個演算法:插入排序。插入排序並不是最直觀的排序演算法,拿它做第乙個講解應該有其他的理由。
通過插入排序的講解,偽**約定、迴圈不變式、演算法分析等最基礎的知識被帶了出來。
此後又講了第二個演算法:合併排序,並引出了演算法設計中的兩種常見型別:增量法(incremental)和分治法(divide-and-conquer)。
選擇排序(selection sort)應該是最直觀的排序方法了。它的偽**如下:
selection_sort(a)
for i <- 1 to length[a] - 1
min <- i
for j <- i + 1 to length[a]
if a[j] < a[min]
then min <- j
swap a[i] and a[min]
演算法有乙個外層迴圈和乙個內層迴圈,外層迴圈次數為 n-1,記憶體迴圈次數為 n-i,其中i為外層迴圈當前步數。因為整個演算法執行時間是下面這種形式:
n-1 + n-2 + n-3 + ... + 3 + 2 + 1 = n(n-1)/2
再者,演算法最佳和最壞情況下的執行時間差別只在第6行「then」那一句上,對內外迴圈次數無任何影響,因此其最佳和最壞情況下的執行時間的θ形式都是 θ(n^2)。
為了有較好的最佳情況執行時間,就必須判斷資料是否處於最佳情況下,若是則直接完成處理,而不是和其他情況用同一種方式處理。
換一種說法,即以最佳情況為預設情況考慮,只有非預設情況才需要處理,預設情況直接放過。
不能改用二分查詢策略改善最壞情況執行時間,因為就算用二分法快速找到了插入點,但是插入這個動作還是需要移動插入點之後的所有已排序元素,所花的時間在多項式角度完全沒有變少。
思路: 1. 既然兩個數的和等於x,那麼必然乙個大於等於x/2,另乙個小於等於x/2。考慮先對集合排序; -- θ(nlgn)
2. 從小到大排序後,用二分法找到x/2分界點a,sa是第乙個大於等於x/2的元素; -- θ(lgn)
3. 對於(s1,s2, ..., s)中每乙個元素i,求出(x - si),再在(sa, s, ..., sn)中,用二分法查詢(x - si),找到就說明存在,找不到就繼續找,直到迴圈完畢;-- θ(nlgn)
最終的最壞情況執行時間為 θ(nlgn) + θ(lgn) + θ(nlgn) = θ(nlgn)。
c), d) 不會做。
通過等式θ(nk + nlg(n/k)) = θ(nlgn),左邊化簡得θ(nlgn + nk - nlgk),所以只要nk - nlgk = 0就和右邊一樣了。這樣就變成求使等式2^k = k成立的k值,和n沒關係了。
而且通過作圖,發現這個等式根本無解……不知道哪兒出問題了,等複習了高數再說吧。
c) 插入排序的執行時間和輸入陣列中的逆序對的數量成正比,結論是猜測出來的,沒經過嚴格證明。理由是求逆序對數目的多項式和求插入排序最壞形況執行時間的多項式一模一樣,都是an^2 + bn - c形式。
d) **見此處:《演算法導論》筆記:第2章 思考題2-4 求逆序對(**)
思路:考慮a,b兩個已排序子陣列合併成a子陣列的情形,把a,b看作乙個陣列ab,如果a中的任一元素都小於b中的任一元素,那麼陣列ab中的逆序對為0。如果a中的任一元素都大於b中的任一元素,那麼陣列ab中的逆序對為length[b]*length[a],這和合併排序裡的乙個動作很類似:當a中的元素都大於b時,會把b首先全部放入a,放完後再開始放a。b先於a放了length[b]次,每次a中剩餘元素個數為length[a],length[b]個length[a]相加後即為逆序對數量。
繼續考察a不是全部大於b的情況,兩者依然相等。
還有一點重要的是,a和b合併之後,並不影響這個整體相對於其他子陣列的逆序對數量。
因此,最終得出以下兩個數目相等:
1) 陣列中的逆序對數量;
2) 合併排序演算法中,每對子陣列合併之時,每乙個b子陣列中的元素放入a子陣列時,a子陣列中的剩餘元素個數之和。
《演算法導論》筆記 第2章 演算法入門
第2章 演算法入門 插入排序 對陣列a進行插入排序 insertion sort a 1 for j 2 to length a 2 do key a j 代表賦值 3 insert a j into the sorted sequence a 1.j 1 4 i j 1 5 while a i k...
《演算法導論》第2章 演算法基礎 個人筆記
insertion sort a for j 2 to a.length key a j i j 1 while i 0 anda i key a i 1 a i i a i 1 key 在insertion sort中,若輸入陣列已排好序,則出現最佳情況,t n n 若輸入陣列已反向排序,則導致最...
演算法導論第2章 演算法基礎
2.1 插入排序 includeusing namespace std void insertion sort int a,int n 宣告 void print int a,int n void insertion sort int a,int n a i 1 key void print int...