題解——冒泡+二分查詢
題解——冒泡+二分查詢
文章目錄
題目連結: 傳送門
題面
描述
有一組資料放在陣列R[ ]
中,R[ ]={9,8,7,6,0,-1,10,-5,-32,66}
,請呼叫氣泡排序函式(自己定義函式),先將陣列進行排序,然後呼叫二分查詢演算法(自己定義函式)查詢某數,分別給出比較次數,每個比較次數佔一行,比較次數為-1
時表示沒找到。
輸入
第1行輸入排序標誌,為1
時,對原陣列先採用升序排序
2
時,對原陣列採用降序排序。
第2行開始輸入待查詢的數。輸入非整數
或^Z
時,結束輸入。
輸出
採用二分查詢法查詢某數時的比較次數,每個比較次數佔一行,比較次數為-1
時表示沒找到。
樣例輸入
1
-1
25
6
樣例輸出
3
-1
1
提示
直接在程式裡定義R[ ]={9,8,7,6,0,-1,10,-5,-32,66}
ps. 這裡有點狠!讓你直接在程式裡定義,結果原題混入一箇中文逗號!
題解
這個題對大家來說陌生的地方可能主要在於輸入要求:
輸入非整數或^Z時,結束輸入。
^Z
其實是ctrl+Z
的意思,這是一個檔案結束符,當你在鍵盤上敲ctrl+Z
的時候,相當於輸入了“檔案結束符”,你的程式必須能讀取“檔案結束符”,並使輸入停止。
我們一步一步來:
首先按題意,定義陣列r
#include <iostream>
using namespace std;
int r[]={9,8,7,6,0,-1,10,-5,-32,66};
ps. 為了方便使用,我們直接把它定義為全域性變數
氣泡排序
升序
void cin_up(){
int t;
for(int i=0;i<10;i++)
for(int j=0;j<9;j++)
if(r[j]>r[j+1]) //升序
t=r[j],r[j]=r[j+1],r[j+1]=t;
}
降序
void cin_down(){
int t;
for(int i=0;i<10;i++)
for(int j=0;j<9;j++)
if(r[j]<r[j+1]) //降序
t=r[j],r[j]=r[j+1],r[j+1]=t;
}
二分查詢
首先需要注意的一點是,二分演算法可能需要根據序列的增減性不同而作出相應調整,如:
-
若待查詢序列為升序,如
0 1 2 3 4 5 6
,要找5
,第一次mid=(0+6)/2=3
,r[mid]=3<5
,此時應該進行的操作是l=mid+1
; -
若待查詢序列為降序,如
6 5 4 3 2 1 0
,還是要找5
,第一次r[mid]=3<5
,此時進行的操作就不是l=mid+1
了,而是r=mid-1
;
因此,我們乾脆就寫兩個二分查詢函式,根據升序/降序的不同選擇性地呼叫它們即可。
二分查詢——升序
int binFind_up(int key){
int L=0,R=9,mid,num=0;
while (L<=R){
num++;
mid=(L+R)/2;
if(r[mid]==key)return num;
else if(r[mid]<key)
L=mid+1;
else
R=mid-1;
}
return -1;
}
二分查詢——降序
int binFind_down(int key){
int L=0,R=9,mid,num=0;
while (L<=R){
num++;
mid=(L+R)/2;
if(r[mid]==key)return num;
else if(r[mid]>key)
L=mid+1;
else
R=mid-1;
}
return -1;
}
輸入
AC做法
int main(){
int n; // 排序標誌n
cin>>n;
if(n==1)
cin_up(); // 採用升序排序
else if(n==2)
cin_down(); // 採用降序排序
int x;
while (cin>>x){ // 符合要求的資料輸入方法
if(n==1)cout<<binFind_up(x)<<endl;
else cout<<binFind_down(x)<<endl;
}
return 0;
}
原理
為什麼可以把cin
直接放在while
的條件裡呢?這就要從cin
函式的返回值說起。函式cin
也是有返回值的。當:
- 遇到檔案結束符
ctrl+Z
的時候,返回0
; - 遇到無效輸入的時候,返回
0
,比如待輸入的數是整數,但你輸入了非整數; - 有效輸入返回
1
;
因此,我們可以直接定義int
型的待輸入變數x
,然後直接將cin>>x
放在while
的判斷條件內,就可以“歪打正著”地實現題目要求的功能。