1.實踐題目名稱:找第k小的數。
2.問題描述:設計乙個平均時間為o(n)的演算法,在n(1<=n<=1000)個無序的整數中找出第k小的數。
3.演算法描述:由函式int partition(int a,int left,int right)、int find(int a,int left,int right,int k) 和 int main() 構成。
(1)函式int partition(int a,int left,int right)的功能是根據a[left]~a[right]中的某個元素x( 如a[left] ) 對a[left]~a[right]進行劃分,劃分後的x所在位置的左段全小於等於x,右段全大於等於x,同時利用x所在的位置還可以計算出x是這批資料按公升非降序排列的第幾個數。
int partition(int a,int left,int right){
將最左邊的數值賦給x;
while(leftwhile下標為right的數值大於或等於x且left小於right
right左移;
交換下標為left和right的數值;
while下標為left的數值小於於或等於x且left小於right
left右移;
交換下標為left和right的數值;
重新賦值x;
返回left;
(2)函式int find(int a,int left,int right,int k),通過呼叫partition函式獲得劃分點,判斷劃分點是否第k小,若不是,遞迴呼叫find函式繼續在左段或右段查詢。
int find(int a,int left,int right,int k){
呼叫partition函式,將其值賦值給變數p;
如果k-1等於p,輸出陣列a中下標為k-1的數值;
如果k-1小於p,遞迴呼叫find在(left,p-1)區間繼續找;
如果k-1大於p,遞迴呼叫find在(p+1,right)區間繼續找;
return 0;
(3)main函式。
int main(){
定義變數n,k;
輸入n,k的值;
定義乙個大小為1000的陣列;
用for迴圈依次輸入陣列a;
呼叫find函式在(n-1,k)區間找陣列a中第k大的數;
return 0;
4.演算法時間及空間複雜度分析(要有分析過程):
時間複雜度:拿到這道題,我第一時間想到的方法就是直接排序然後輸出第k小的數。但是題目要求設計乙個平均時間為o(n)的演算法,而第乙個方法的時間複雜度不符合題目要求,所以並不可行。因此還是要運用學過的分治法和快速排序法。先用陣列中的元素x對陣列進行劃分,分成左右兩個區域,然後判斷x是否為題目要求的第k小的數,若是,則輸出,若不是則繼續劃分查詢,以此類推,直到找到為止。這樣就能達到題目要求的平均時間o(n)了。
空間複雜度:find函式中運用了遞迴,所以空間複雜度應為o(log n)。
5.心得體會(對本次實踐收穫及疑惑進行總結)
本次上機實踐學會了用函式partition()對陣列進行劃分,相比於以往較為簡單粗暴的直接排序然後輸出的演算法,更加的巧妙和高階。這一次在題目的要求之下學會了如何區運用更加精巧和高效率的演算法去同乙個解決問題。上機實踐過程中前期對find函式的設計和快速排序演算法不太理解,程式設計進度有點被卡住。在實踐結束後,對函式的遞迴呼叫,分治法的思想以及陣列區域的劃分有了更深的了解和認識。
演算法第二章上機實踐報告
實踐題目名稱 找第k個小的數 問題描述 設計乙個平均時間為o n 的演算法,在n 1 n 1000 個無序的整數中找出第k小的數。演算法描述 就是先假設a left 為這個分界值x,然後排序。比較x是不是第k個如果是,返回這個值。如果不是比較一下x和a k 的大小,如果xa k 遞迴在x的右邊找 演...
演算法第二章上機實踐報告
7 1 最大子列和問題 20分 給定k個整數組成的序列,連續子列 被定義為,其中 1 i j k。最大子列和 則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試資...
演算法第二章上機實踐報告
1,實踐題目名稱 最大子列和問題 給定k個整數組成的序列,連續子列 被定義為,其中 1 i j k。最大子列和 則被定義為所有連續子列元素的和中最大者。例如給定序列,其連續子列有最大的和20。現要求你編寫程式,計算給定整數序列的最大子列和。本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試...