算法导论中C语言代码,算法导论-学习笔记与进度
算法導論 閱讀進度
第一部分 基礎知識
第一章 計算中算法的角色 Done
1.1 算法
輸入與輸出
算法可以解決哪些問題
數據結構
技術
一些比較難的問題
1.2 作為一種技術的算法
效率
算法和其他技術
第二章 算法入門 Done
2.1 插入排序
偽代碼如下:
INSERTION_SORT(A)
for j = 2 to length[A]
do key = A[j]
i = j-1
// 將其與已經排好序的數組進行挨個比較
while i>0 and A[i] > key
do A[i+1] = A[i]
i = i-1
A[i+1] = key
原理
其實就是在每次進入一個元素key后,將其與已經排好序的序列進行比較,如果key值小于序列的第一個值(默認為從小到大排序),那么就表明該key應該置入這個序列當中,并且將比較過的元素自動向后移動,以騰出空間放置key。最后將key值置入空位中。
現(xiàn)實中就是在接牌時,插入和調整撲克牌順序的問題了,算法復雜度為O(n^2)
插入排序采用的是增量方法(incremental),采用分治法的合并排序時間復雜度為O(nlgn)
分治法
- 分解
- 解決
- 合并
主要在于合并算法MERGE(A, p, q, r)
偽代碼如下:
MERGE(A, p, q, r)
n1 = q-p+1
n2 = r-q
for i = 1 to n1
do L[i] = A[p+i-1]
for j = 1 to n2
do R[j] = A[q+j]
L[n1+1] = -oo
R[n2+1] = -oo
i = j = 1
for k = p to r
do if L[i] <= R[j]
then A[k] = L[i]
i = i+1
else
A[k] = R[j]
j = j+1
原理
首先將輸入數組分割,然后在對分割后的數組進行一一比較,如果L的元素小,就將其輸出至目的數組A,如果R小,則輸出R至A.
此時MERGE-SORT算法就清晰了,如果將一個數組通過遞歸不斷將其分割,最終分割為每個數組只有一個元素,那么使用MERGE時,就能夠將此二元素排序,然后對4元素排序,然后是8元素....
偽代碼如下:
MERGE-SORT(A, p, r)
if p
then q = (p+r)/2
MERGE-SORT(A, p ,q)
MERGE-SORT(A, q+1, r)
MERGE(A, p , q, r)
冒泡排序
偽代碼如下:
BUBBLE-SORT(A)
for i = 1 to length[A]
do for j = length[A] downto i+1
do if A[j] < A[j-1]
then exchange A[j], A[j-1]
通過不斷交換相鄰的兩個反序元素達到排序的目的,時間復雜度為O(n^2)
1----n-1
2----n-2
3----n-4
....
n-1----1
即
1+2+3+4+....+n = n(n+1)/2,所以時間復雜度為O(n^2)
第三章 函數的增長 Done
第四章 遞歸 Done
遞歸式 T(n) = aT(n/b) + f(n), 其中a>=1, b>1, f(n) 是給定函數
4.1 代換法
猜測解的形式
用數學歸納法找出真正有效的常數
4.2 遞歸樹方法
仔細畫出遞歸樹
4.3 主方法
是求解遞歸式T(n)的食譜方法。
主方法依賴于定理4.1主定理 設a>=1 和 b >1為常數,設f(n)為一函數,T(n)由遞歸式
T(n) = aT(n/b) + f(n)
對非負整數定義,其中n/b 指上頂或者下底,那么T(n)可能有如下的漸進界
...
主要是針對f(n),a,b等值。
第五章 概率分析與隨機化算法
5.1 雇用問題
概率分析,隨機算法。
使用概率分布預測輸入值的分布,以此來幫助分析算法平均情況行為的。
5.2 指示器隨機變量
I(A) = 1,如果A發(fā)生的話;0,如果A不發(fā)生的話。
5.3 隨機算法
無法得到輸入分布,考慮使用隨機算法。
隨機排列數組
許多隨機算法通過排列給定的輸入數組來使輸入隨機化。
一個常用方法是為每個數組元素A[i]賦一個隨機的優(yōu)先級P[i],然后按照優(yōu)先級對數組進行排序,過程PERMUTE-BY-SORT,花費O(nlgn)
原地排列給定的數組,過程RANDOMIZE-IN-PLACE花費O(n)
5.4 進一步使用
1 生日悖論
一個房間的人數需要達到多少,使得兩個人生日相同的機會達到50%?分析所有人生日互不相同的概率,其補就為至少兩人生日相同。
因此 Pr{Bk} = 1(n-1/n)(n-2/n)(n-3/n)....(n-k+1/n)=1(1-1/n)*(1-2/n)...(1-(k-1)/n)
最后分析得出至少23人在一個房間里,概率就能夠為1/2。火星為38個人
2 球與盒子
第二部分 排序和順序統(tǒng)計學. Done
第六章 堆排序 Done
二叉堆數據結構可以被視為一顆完全二叉樹。樹的每一層都是被填滿的,最后一層可能除外。
父節(jié)點
PARENT(i)
return [i/2]
LEFT(i)
return 2i
RIGHT(i)
return 2i+1
有兩種:最大堆和最小堆,在這兩種堆中,節(jié)點內的數組都要滿足堆特性,在最大堆中,除了根以外的每個節(jié)點,有
A[PARENT(i)] >= A[i]
根元素為最大值。
最小堆剛好相反。
MAX-HEAPIFY. 保持堆的性質,最大堆性質,根或者子根都是樹最大元素,O(lgn)
對A[i]的這顆字數執(zhí)行最大堆化。
算法如下:
MAX-HEAPIFY( A, i )
l = LEFT(A[i])
r = RIGHT(A[i]
If l <= heap-size(A) and A[l] > A[i]
then largest = l
else largest = i
If r <= heap-size(A) and A[r] > A[largest]
then largest = r
If largest != i
then exchange(A[i], A[largest])
MAX-HEAPIFY(A, largest)
建堆 Build-MAX-HEAP, 對每一顆非葉子節(jié)點樹執(zhí)行最大堆化,直至根元素。
自n/2 處開始遞減,循環(huán)執(zhí)行Max-HEAPIFY,運行時間的界為O(n)
BUILD-MAX-HEAP(A)
heap-size[A] = length[A]
for i = length[A]/2 downto 1
do MAX-HEAPIFY(A, i)
堆排序 HEAPSORT 自葉節(jié)點向跟元素遞減,交換跟元素和葉節(jié)點,接著調用MAX-HEAPIFY, 保持該子樹的最大堆性質,即可完成節(jié)點自小到大排序,時間復雜度為O(nlgn)
原理
每次都將最大的根元素換至末尾的葉節(jié)點,這一操作能夠將最大元素調到最后,并且排除出堆,然后再一次構造最大堆,次最大元素又被調節(jié)到根元素位置,然后再一次將其換至葉節(jié)點,這樣,不斷循環(huán),就能夠將元素在數組中從小到大排列。
HEAPSORT(A)
BUILD_MAX_HEAP(A)
for i = length[A] downto 2
do exchange(A[1], A[i])
heap-size[A] = heap-size[A] - 1
MAX-HEAPIFY(A,1)
最大優(yōu)先級隊列,最小優(yōu)先級隊列的應用如圖所示。
第七章 快速排序 Done
QUICKSORT(A,p, r)
If p < r
Then q = PARTITION(A, p, r )
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
最初調用時,QUICKSORT(A, 1, length(A) )
其中PARTITION(A, q, r )算法如下
x = A[r]
i = p-1
For j = p to r-1
Do If A[j] <= x
Then i += 1
Exchange(A[i], A[j])
Exchange(A[i+1], A[r])
Return i + 1
分區(qū)算法 不斷將數組分為四個區(qū):
- 第一區(qū) 小于 x的區(qū)間 A[p, i]
- 第二區(qū) 大于x的區(qū)間 A[i+1, j]
- 第三區(qū)間 尚未比較的區(qū)間 A[j+1, r-1]
- 第四區(qū)間 主元 A[r]
每一次運行都是O(n)
總共需要遞歸調用O(log n),因此算法時間復雜度為O(n log n)
有時我們需要對樣本加入一些隨機化數據,以便對于所有輸入,都能得到較好的平均性能,因此,采用隨機選擇主元的快速排序隨機化版本。
主要是對分區(qū)操作進行修改
RAMDOMIZED-PARTITION(A, p, r)
i = random(p, r)
Exchange(i , r)
Return PARTITION(A, p, r)
新的排序算法修改如下:
RANDOMIZED-QUICKSORT(A, p, r )
If p < r
then q = RANDOMIZED-PARTITION(A, p, r)
RANDOMIZED-QUICKSORT(A, p, q-1)
RANDOMIZED-QUICKSORT(A, q+1, r)
第八章 線性時間排序(即時間復雜度為O(n)) Done
合并排序和堆排序在最壞情況下,達到上界O(nlogn),快速排序在平均情況下達到此上界,最壞O(n^2)
比較排序,非比較排序
8.1 排序算法的時間的下界
比較排序可以抽象為決策樹模型,比如三個值的比較決策結果又3!= 6
定理8.1 任意一個比較排序的算法在最壞情況下,都需要做O(nlgn)次的比較
推論8.2 堆排序和合并排序都是漸進最優(yōu)的比較排序算法。
8.2 計數排序**
比較有趣的一個排序算法,使用三個數組空間A,B,C。
統(tǒng)計各個值出現(xiàn)的次數.
C[A[j]] = C[A[j]] +1
可見對于C的空間要求將會比較大,只適用于數值比較小的空間。
這樣的排序將會導致各個值A[j]的出現(xiàn)次數按照A[j]值的大小在C中依次由小到大排列。然后計算出C中每個值之前出現(xiàn)多少個值,進而計算出該值所占的位置。
算法如下:
COUNTING-SORT(A, B, k)
for i=0 to k
do C[i] = 0
// 計算A[i] 各個值出現(xiàn)的次數
for j=1 to lenght[A]
do C[A[j]] = C[A[j]]+1
// 計算小于或者等于C[i]值出現(xiàn)的次數
for i=1 to k
do C[i] = C[i]+C[i-1]
// 將A[j]的值按照出現(xiàn)的位置置入B中,并將該值的出現(xiàn)次數減一,使與之相同的值自動排在A[j]的前一個位置
for j = length[A] downto 1
do B[C[A[j]]] = A[j]
C[A[j]] = C[A[j]]-1
該算法很繞,但比較穩(wěn)定,運行時間為O(n)
8.3 基數排序
基數排序是對具有多個關鍵字域的記錄進行排序,比如年月日。
RADIX-SORT(A,d)
for i = 1 to d
do use a stable sort to sort array A to digit i
可以將一個32位的字視為4個8位的數字,于是就可以將k 縮小至255,數位d變?yōu)?.
同樣的,利用計數排序作為中間穩(wěn)定排序的基數排序不是原地排序,占用空間較大。盡管基數排序執(zhí)行的遍數可能比快速排序少,但每一遍所需的時間要長得多。因此一般還是使用快排,因為快排能夠有效的利用硬件緩存,同時也是個原地排序。
8.3 桶排序
輸入需要符合均勻分布,即可以以線性時間O(n)運行。計數排序的假設輸入由小范圍內整數構成,而桶排序假設輸入由一個隨機過程產生,該過程均勻分布在區(qū)間(0,1]
算法
BUCKET-SORT(A)
n = length(A)
for i = 1 to n
do insert A[i] into list B[nA[i]]
for i = 0 to n-1
do sort list B[i] with insertion sort
concatenate the lists B[0],B[1],....
B[n-1] together in order
第九章 中位數和順序統(tǒng)計學 Done
約定
取下中位數
本章討論從一個由n個不同數值構成的集合中選擇第i個順序統(tǒng)計量的問題。選擇問題的定義如下:
輸入:一個包含n個不同的數的集合A和一個數i, 1=
輸出: 元素x屬于A,它恰大于A中其他的i-1個元素。
最大值和最小值
比如MINIMUM(A)
min = A[1]
for i = 2 to length[A]
do if min > A[i]
min = A[i]
return min
通過n-1比較得出,時間復雜度為O(n)
最大值也是如此。
同時計算最大值和最小值,如使用獨立比較需要比較2(n-1)次。
可通過每次輸入一對數據,然后將其中大的于最大值比較,小的與最小值比較,每個元素比較三次,但只需運行n/2次,所以總的比較次數是3(n/2)次。
9.2 以期望線性時間做選擇
使用RANDOMIZED-SELECT 算法,以第七章快速排序算法為模型,也是對輸入數組進行劃分,但只處理劃分的一邊,該邊通過與需要選擇的位計算而出,期望運行時間為O(n)
RANDOMIZED-SELECT算法利用RADOMIZED-PARTITION程序,返回數組A[p..r]中第i小的元素
RANDOMIZED-SELECT(A, p, r, i)
if p = r
then return A[p]
q = RANDOMIZED-PARTITION(A, p, r)
k = q - p + 1
if i = k
then return A[q]
elseif i < k
then return RANDOMIZED-SELECT(A, p, q-1, i)
//注意i的位置將會做相應的調整,i始終只是相對位置,而q,r都是指在整個數組中的位置
//因此在比較i和k的位置時,是通過計算k的相對位置來與i比較的。
else return RANDOMIZED-SELECT(A, q+1, r, i-k)
按照我的理解,似乎不需要使用i的相對位置,原始位置應該就可以,感覺上沒有限制。
結論,在平均情況下,任何順序統(tǒng)計量特別是中位數,都可以在線性時間內O(n)得到。
9.3 最壞情況線性時間的選擇
最壞情況運行時間為O(n)的SELECT算法。采用快速排序的確定性劃分算法PARTITION,并做了相應的修改。
- 將輸入數組劃分為n/5個組,每組5個
- 尋找n/5個組中的每一組中位數,首先對每組中的元素進行插入排序(插入排序在元素數量較小的情況下有著O(n)的復雜度)然后從排序過的數組中選出中位數。
- 在第二步中選出的中位數,遞歸調用SELECT選出一個中位數x
- 利用修改過的PARTITION過程,按照中位數的中位數x,對輸入數組進行劃分,讓k比劃分地區(qū)的元素數目多1,所以x就是第k小元素,并且有n-k個元素在劃分的高區(qū)。
- 如果i = k ,則返回x,否則,如果ik, 則在高區(qū)遞歸調用尋找第(i-k)個最小元素。
本章結論
本章中選擇算法之所以具有線性時間,是因為這些算法并沒有進行排序。線程時間的行為并不是因為對輸入做假設所得到的結果。在比較模型中,即使是在平均情況下,排序仍然需要O(nlgn)的時間,所以從漸進意義上來看,排序和索引方法的效率是不高的。
第三部分 數據結構
第十章 基本數據結構. Done
第十一章 散列表. Done
第十二章 二叉查找樹. Done
第十三章 紅黑樹. Undone
第八部分 附錄:數學基礎知識
A. 求和. Done
B. 集合等離散數學結構. Done
集合
關系
函數
圖
樹
自由樹
有根樹和有序樹
二叉樹和位置樹
C. 計數和概率. Undone
C.1 計數
串
在有限集合S上構造一個長度為k的串稱為K串。直觀上,為了在n元集上構造一個k串,有n種方法選擇第一個元素,同樣地,也有N種方法選擇第二個元素,這樣一次進行K次,從而K串的數目為nnn*...n = n^k.
最形象的就是車牌號了。
排列
有限集S的排列是S中所有元素的有序序列,且每個元素僅出現(xiàn)一次。一個N元集的集合有n!種排列,第一個元素有n種選擇,第二個有n-1種選擇,第三個有n-2種選擇...
集合S的k排列是S中k個元素的有序排列,且每個元素出現(xiàn)一次。因此N元集合的K排列數目是
n(n-1)(n-2)(n-3)(n-4)...(n-k+1) = n!/(n-k)!
組合
n元集的K組合就是S的k子集,n元集的k組合的數目可以用排列的數目來表示,對每個k組合,它的元素恰好有k!中排列,每個都是n元集的一個不同的k排列。因此,n元集的k組合數目是其k排列的數目除以k!。這個數量為
n!/(k!(n-k)!)
組合與排列的區(qū)別是,組合中k元祖是無序的,而排列是有序的,意味著組合的元祖對應著k!種不同的排列元祖。
因此在計算時需要除去每個元祖的其他的有序排列。
二項式系數
二項式界
下界
= n!/k!(n-k)! 展開>= (n/k)^k
再利用斯特林近似式得上界
<= n^k/k! <= (en/k)^k
C.2 概率
條件概率Pr{A|B} 讀作在事件B發(fā)生的條件下,事件A發(fā)生的概率
Pr{A|B} = Pr{A交B}/ Pr{B}
A交B是時間A發(fā)生,B也發(fā)生的事件,因此可以認為這是B中的一個基本事件,因此該事件占整個B事件的概率就是Pr{A交B}/ Pr{N},也即Pr{A|B}
如果Pr{A交B} = Pr{A} Pr{B},則稱連個事件獨立。
貝葉斯定理
Pr{A交B} = Pr{B} Pr{A|B} = Pr{A} Pr{B|A}
通過交換律,可得如下貝葉斯定理
Pr{A|B} = Pr{A} Pr{B|A}/Pr{B}
C.3 離散隨機變量
隨機變量X的概率密度函數
f(x) = Pr{X=x}
隨機變量的期望值
E[X] = ∑xPr{X=x}
方差
Var[X] = E[(X-E[X]^2)]
= E[X^2]-E^2[X]
C.4 幾何分布與二項分布
幾何分布
假設進行一系列的伯努利實驗,每次實驗成功的概率是P,失敗的概率是q=1-p,在取得一次成功前要進行多少次實驗?因為在取得一次成功前有k-1次失敗,從而有
Pr{X=k} = q^(k-1)p
期望 1/p
二項分布
因為有(n k) 種方法從n次實驗中選取k次成功的試驗,且每次發(fā)生的概率是p^k*q^(n-k)
Pr{X=k} = (n k)p^k*q^(n-k)
期望E[X] = np, 方差 Var[X] = npq
發(fā)自我的 iPad
總結
以上是生活随笔為你收集整理的算法导论中C语言代码,算法导论-学习笔记与进度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言结构体讲解,C语言基础之结构体讲解
- 下一篇: 计算机二级c语言题库缩印,2011年9月