2019年春季學期第四周作業:
作業課程 | C語言程序設計II |
作業要求 | 2019年春季學期第四周作業 |
課程目標 | 背熟棧,隊列,向量函數 |
從作業中得到的幫助 | 更加熟練兩種基本排序算法(冒泡排序和選擇排序) |
參考文獻 | 挑戰程序設計 |
第一題:
7-1 找鞍點 (20 分)
一個矩陣元素的“鞍點”是指該位置上的元素值在該行上最大、在該列上最小。
本題要求編寫程序,求一個給定的n階方陣的鞍點。
輸入格式:
輸入第一行給出一個正整數n(1≤n≤6)。隨后n行,每行給出n個整數,其間以空格分隔。
輸出格式:
輸出在一行中按照“行下標 列下標”(下標從0開始)的格式輸出鞍點的位置。如果鞍點不存在,則輸出“NONE”。題目保證給出的矩陣至多存在一個鞍點。
輸入樣例1:
4 1 7 4 1 4 8 3 6 1 6 1 2 0 7 8 9
輸出樣例1:
2 1
輸入樣例2:
2 1 7 4 1
輸出樣例2:
NONE
此題是一道簡單的搜索題,也就是先確認一個點,然后沿4個方向搜索到不滿足條件的數(不越界的情況下),然后返回需要的值。由於題目給的條件非常非常非常小,所以不需要考慮復雜度,邏輯通了隨便寫。
AC代碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int arr[10][10];//n<6,直接定義一個全局變量 5 bool solve(int n,int x,int y){ 6 for(int i = 0; i < n ; i++) 7 if(arr[x][y]<arr[x][i])return false;//搜索行,找到一個大於確認的點的值直接返回 8 for(int j = 0; j < n ; j++) 9 if(arr[x][y]>arr[j][y])return false;//搜索列,找到一個小於確認的點的值直接返回 10 11 return true; 12 } 13 14 int main ( int argc , const char * argv[]) 15 { 16 int n,flag; 17 cin>>n; 18 for(int i=0;i<n;i++)for(int j=0;j<n;j++){cin>>arr[i][j];}//給數組賦值 19 20 for(int i=0;i<n;i++) 21 for(int j=0;j<n;j++) 22 if(solve(n,i,j)){cout<<i<<" "<<j;flag++;}//找到滿足條件的鞍點就輸出(雖然題目說給的矩陣至多一個鞍點,但懶得弄就直接判斷所有的點是否為鞍點吧) 23 if(!flag)cout<<"NONE";//沒有鞍點則輸出NONE 24 return 0; 25 }
設計思路
本題調試過程中遇到的問題及解決方法
由於是一遍AC的,暫無任何疑問。
運行結果截圖
第二題
7-2 選擇法排序 (20 分)
本題要求將給定的n個整數從大到小排序后輸出。
輸入格式:
輸入第一行給出一個不超過10的正整數n。第二行給出n個整數,其間以空格分隔。
輸出格式:
在一行中輸出從大到小有序的數列,相鄰數字間有一個空格,行末不得有多余空格。
輸入樣例:
4 5 1 7 6
輸出樣例:
7 6 5 1
首先提一下,三種基本排序方法(冒泡,選擇,插入)在N久之前就寫了很多遍的東西..這次寫也沒花多久直接一遍過了,只能說這周問題比較面向初次了解排序算法的人,我接下來會把選擇排序和“挑戰題”冒泡排序(挑戰題有加分吧?手動滑稽)稍微寫詳細點,因為自己也很久沒寫過了,幫助記憶一下。
AC代碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 void solve(int arr[],int n){ 5 for(int i=0;i<n-1;i++){ //首先理所當然solve里面第一個要做的事情就是做一個內外循環,外循環要少一次,防止最后兩個元素重復。 6 int maxs=arr[i]; //重置maxs的值,maxs就是各輪循環處理中,第i號到第N-1號元素中的最大值 7 int sz_zb=i; //重置sz_zb的值,sz_zb就是各輪循環處理中,第i號到第N-1號元素中最大值的下標 8 for(int j=i;j<n;j++){if(maxs<arr[j]){maxs=arr[j] ; sz_zb=j;} } //找出第i號到第N-1號中的最大值及其下標 9 int tmp = arr[i] ; 10 arr[i] = maxs; //交換第i號和對應的最大值的元素的位置 11 arr[sz_zb] = tmp; 12 } 13 for(int i=0;i<n;i++) 14 if(i<n-1) 15 cout<<arr[i]<<" "; 16 else cout<<arr[i]; //從大到小輸出數組 17 18 } 19 20 int main ( int argc , const char * argv[]) 21 { 22 int n,num[12]; 23 cin>>n; 24 for(int i=0;i<n;i++) 25 cin>>num[i]; 26 27 solve(num,n); 28 return 0; 29 }
設計思路
本題調試過程中遇到的問題及解決方法
雖然是一遍AC的,但還是提醒一下,一定要理解內外循環的概念及作用,不然排序會出錯
運行結果截圖
注意一下,選擇排序的復雜度,假設數據總數為N,那么無論在哪一種情況下,選擇排序都要進行(N-1)+(N-2)+.....+1=(N^2-N)/2次比較運算,用於搜索未排序部分的最小值,因此該算法的復雜度與N^2基本成正比,及復雜度數量級為O(N^2).使用時要看題目條件范圍是否過大,如果過大建議選擇其他排序算法。
挑戰題
7-1 冒泡法排序 (10 分)
輸入1個正整數n(1<=n<=10),然后輸入n個整數並存放在數組中,將這n個整數從大到小排序后輸出,相鄰數字間有一個空格,行末不得有多余空格。
輸入格式:
輸入第一行給出一個不超過10的正整數n。第二行給出n個整數,其間以空格分隔。
輸出格式:
在一行中輸出從大到小有序的數列,相鄰數字間有一個空格,行末不得有多余空格。
輸入樣例:
4 75 71 77 76
輸出樣例:
77 76 75 71
冒泡排序算法的時間復雜度與選擇排序的時間復雜度是基本一樣的,也是要做(N^2-N)/2次比較,所以復雜度也為O(N^2).只是排序的過程略有不同,選擇排序是每次遍歷,找出未排序的數中最大的一個,然后將它放在最前面,而冒泡排序則是從第一個數(未排序好的數)開始,一個一個往后比較,遇到比自己大的則交換位置,直到無法交換為止,最后排完所有的數后一定是從大到小的順序。
AC代碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 void solve(int arr[],int n) 5 { 6 for(int i = n - 1 ; i > 0 ; i--) 7 for(int j = 0 ; j < i ; j++) 8 { 9 if( arr[j] < arr[j+1] ){int tmp = arr[j];arr[j]=arr[j+1];arr[j+1]=tmp;} 10 } 11 12 for(int i = 0 ; i < n ; i++) 13 if(i<n-1)cout<<arr[i]<<" "; 14 else cout<<arr[i]; 15 } 16 int main ( int argc , const char * argv[] ) 17 { 18 int n; 19 cin>>n; 20 int arr[12]; 21 for( int i = 0 ; i < n ; i++)cin>>arr[i]; 22 solve(arr,n); 23 return 0; 24 }
設計思路
本題調試過程中遇到的問題及解決方法
此題是一道較為簡單的基礎排序題,未遇到任何問題。
運行結果截圖
寫到這里為了能更加區別冒泡和選擇排序的區別,我改一下代碼將每一次排序的過程運行圖發出來。
冒泡排序:
選擇排序:
稍微注意觀察一下,排序過程的差異很明顯。
最后還是分享一下利用partition進行快排的算法,是一個很經典及實用的排序算法,博客地址:https://www.cnblogs.com/xiangqi/p/10485379.html
學習總結: | 存在的問題 | 心得 | 完成作業消耗時間 | 本周學習內容 |
第一周 | 對文件讀取數據的運用不是很熟練 | 多去看關於刷題的書籍,有助於提高自己寫題能力,實在不會的可以參考大佬的代碼,加以自己理解之后去默寫幾遍 | 半個小時左右 | 文件輸入,BFS,DFS,PARTITION算法及簡單的貪心算法 |
第二周 | 對單純用數組完成雙向鏈表的操作還是太生疏了,說明對雙向鏈表的運作原理不熟 | 推薦兩本比較好的書《挑戰程序設計》《算法競賽》 | 半個小時左右 | vector數組及list雙向鏈表操作 |
再分享本周預習題的解法,寫到了另外一篇博客,這里是地址:https://www.cnblogs.com/xiangqi/p/10573623.html
------------------------不用看了,這里沒了-----------------------