實驗目的:
掌握選擇排序、氣泡排序、合併排序、快速排序、歸併排序的演算法原理
分析不同排序演算法的時間效率和時間複雜度,以及理論值與實測資料的對比分析。
一、氣泡排序
演算法偽**:
for i=1 to n
for j=0 to n-i
if ( data[j]>=data[j+1])
swap(data[j],data[j+1])
演算法思路:
第乙個迴圈表示n-1趟即可完成排序。每一趟將最大的數調換位置到未排序數字的末尾。
資料分析:
由圖1.氣泡排序的曲線圖可以看出氣泡排序的時間增長基本符合二次增長,先選取以n=10000的實際時間t1作為理論時間的基準。
當n=20000時,t2=t1*(2/1)2、
當n=30000時,t3=t1*(3/1)2,以此類推做出表1。
資料規模
實際時間(ms)
171.1
669.75
1513.8
2580.85
3956.85
理論時間 (ms)
表1.10000為基準
圖1.氣泡排序
由圖一可得,以n=10000為基準時,n=50000時理論和實際有一些偏差。懷疑是n=10000的實測時間可能是高於平均時長,所以我又以n=50000為基準做出下表。
資料規模
實際時間(ms)
171.1
669.75
1513.8
2580.85
3956.85
理論時間 (ms)
158.274
633.096
1424.466
2532.384
3956.85
表2.以n=50000為基準
兩條曲線基本擬合,說明當n=10000時所測得的實際時間比平均時間略長一點,所以導致後面的理論值偏大。
時間複雜度分析:
氣泡排序最好情況:資料本來已是正序,僅需要進行n-1次比較操作即可,時間複雜度為o(n)
氣泡排序最壞情況:資料是倒序排列,需要進行次的比較操作,還需要進行3* n(n-1)/2次的賦值移動操作。時間複雜度為o(n2)
氣泡排序的平均時間複雜度:第i趟排序需要進行n-i次比較,一共要進行n-1趟排序,所以由求和公式得一共要進行n(n-1)/2次的比較操作,移動操作次數也在n2級別,所以時間複雜度為o(n2)
二、選擇排序
演算法偽**:
for i=0 to n-1
if i!=k
swap(data[i],data[k])
}
演算法思路:
在未排序資料中找到最小值,放到起始位置當成已排序資料,然後再從剩餘序列中重複上述過程直到初始位置為陣列最末尾。
資料分析:
由圖2.選擇排序的曲線圖可以看出選擇排序的時間增長基本符合二次增長,先選取以n=10000的實際時間t1作為理論時間的基準。
當n=20000時,t2=t1*(2/1)2、
當n=30000時,t3=t1*(3/1)2,以此類推做出表3
資料規模
實際時間(ms)
41.25
167.1
350.15
595.75
908.65
理論時間 (ms)
41.25
371.25
1031.23
表3.以10000為基準的選擇排序
由圖2看出當資料規模到達40000、50000時理論值與實際值的誤差較大,所以再以50000的實測時間作為基準,做出表4
資料規模
實際時間(ms)
41.25
167.1
350.15
595.75
908.65
理論時間 (ms)
36.346
145.384
327.114
581.536
908.65
表4.以50000為基準的選擇排序
以50000實測時間為基準時做出的理論值**更貼近實際時間,我認為n=10000的實測時間比平均時間略大,且由曲線貼合程度也能得出此結論。
圖2.選擇排序
時間複雜度分析:
選擇排序最好情況:資料已經為正序,則需要進行n(n-1)/2次比較操作但是移動操作次數為0。
選擇排序最壞情況:資料為完全反序,則需要進行n(n-1)/2次比較操作和3(n-1)次移動操作。
選擇排序的平均時間複雜度:需要選擇n-1次最小數,第i次選擇時需要遍歷大小為n-i的陣列。所以比較操作一定需要進行n(n-1)/2次。所以無論移動次數進行多少次,平均時間複雜度為o(n2).
三、插入排序
演算法偽**:
for i=1 to n-1
}merge(data,low,mid,high)
int partition(data,low,high)
data[high]=key
return high #返回基準值的位置
}
演算法思路:
選取乙個基準值,將比基準值大的元素移到基準右邊,比基準值小的移動到左邊,然後在左右兩個子集中,重複上述操作直到所有子集僅有乙個元素。
資料分析:
選取以n=10000的實際時間t1作為理論時間的基準。
當n=20000時,t2≈t1*2
當n=30000時,t3≈t1*3,以此類推做出表7
資料規模
實際時間(ms)
1.32
2.34.05
5.37.4
理論時間 (ms)
1.32
2.64
3.96
5.28
6.6表7.10000為基準
由圖五可以看出快速排序的時間增長基本符合線性增長的規律,且實測時間與理論時間曲線基本吻合,誤差都在0.1ms級別。
時間複雜度分析:
快速排序的最好情況:每一次選取的基準都恰好為子集的中間值,則左右子集的元素個數基本一樣,則此時遞迴樹的深度為logn,在每一層中的比較次數都小於等於n,此時時間複雜度為o(nlogn)
快速排序的最壞情況:每一次選取的基準都恰好為子集中的最大或最小值,則子集的規模僅比原規模小1,所以需要做n-1次劃分。第i次劃分開始時,區間長度為n-i+1,所需的比較次數為 n-i。所以這種情況下比較次數達到最大值n(n-1)/2,所以此時時間複雜度為o(n2)。
快速排序的平均時間複雜度:最壞情況的產生與演算法或者是原待排陣列無關,所以快速排序的平均時間複雜度由遞迴樹方法可得為o(nlogn)。不考慮最壞情況的理由如下:每次劃分後左右兩個子集是無序的,每次選取子集第乙個元素作為基準時,每一次此元素恰好是子集中的最值的概率非常小。
六、五種排序演算法的比較
當資料規模從n=100變化到n=100w時,每種演算法的時間增長折線圖如下:
由圖可知:快排》
歸併》插入》選擇》冒泡。
(1) 時間複雜度同為o(n2),為什麼又分快慢?
答:選擇排序快於氣泡排序是因為,氣泡排序的移動次數很多,每當發現前者大於後者的時候就需要進行交換,移動次數可以達到n2級別,而選擇排序最壞的情況下的移動次數也僅為3(n-1)次。
而插入排序比選擇排序要快的原因則是每一趟選擇排序要在剩下的資料中找到最小元素,則第i趟排序必須需要進行n-i次的比較。而插入排序將新元素插入到已排好序列中時,不一定每一次都要與前面的每乙個元素進行比較,除非每一次要插入的元素比已排好序列中的每個值都小,所以插入排序要快於選擇排序。
(2) 時間複雜度同為o(nlogn),為什麼快排更快呢?
答:快速排序快在資料賦值操作少。在歸併排序中,每兩個子集合並時都要將兩子集中所有元素寫入到新陣列中儲存。則在每一層的歸併中資料的寫入操作一定為n。而在快速排序中,每乙個子集中,並不需要移動每乙個元素,因為很多比基準小的元素本來就在基準左邊,比基準大的元素本來就在基準右邊。所以同為o(nlogn),快速排序又更勝一籌。
快速排序演算法的實驗
快速排序演算法 原理 從數列中挑出乙個元素,稱為 基準 pivot 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面 相同的數可以到任一邊 在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽 partition 操作。遞迴地 recursive 把小...
演算法導論 比較排序演算法對比實驗
演算法導論 這本書介紹了5種比較排序演算法 插入排序 氣泡排序 歸併排序 堆排序 快速排序。我們現在通過實驗來對比這5種排序演算法的執行時間。用隨機數發生器生成不同長度的陣列,將每種演算法應用於不同長度的陣列,統計程式的執行時間,從而得得每種演算法的期望執行時間隨輸入規模的變化曲線。1.全部5種演算...
8種排序演算法
學習了這麼多的排序演算法,還沒有做個總結,呵呵 氣泡排序 氣泡排序是最慢的排序演算法。在實際運用中它是效率最低的演算法。它通過一趟又一趟地比較陣列中的每乙個元素,使較大的資料下沉,較小的資料上公升。它是o n 2 的演算法。快速排序 快速排序是乙個就地排序,分而治之,大規模遞迴的演算法。從本質上來說...