題目--找鞍點 及 選擇排序和冒泡排序


 

2019年春季學期第四周作業:

 

作業課程 C語言程序設計II
作業要求 2019年春季學期第四周作業
課程目標 背熟棧,隊列,向量函數
從作業中得到的幫助 更加熟練兩種基本排序算法(冒泡排序和選擇排序)
參考文獻 挑戰程序設計

 

第一題:

7-1 找鞍點 (20 分)

一個矩陣元素的“鞍點”是指該位置上的元素值在該行上最大、在該列上最小。

本題要求編寫程序,求一個給定的n階方陣的鞍點。

輸入格式:

輸入第一行給出一個正整數n(1n6)。隨后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

------------------------不用看了,這里沒了-----------------------


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM