資料結構與演算法基礎-01-二分查詢
阿新 • • 發佈:2018-11-05
二分查詢
注:本題目源自《浙江大學-資料結構》課程,題目要求實現二分查詢演算法。
函式介面定義
Position BinarySearch( List L, ElementType X );
其中List
結構定義如下:
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 儲存線性表中最後一個元素的位置 */
};
並且L
是使用者傳入的一個線性表,其中**ElementType
元素可以通過
>、==、<
**進行比較,並且題目保證傳入的資料是遞增有序的。函式BinarySearch
要查詢X在Data中的位置,即陣列下標(注意:元素從下標1開始儲存)。找到則返回下標,否則返回一個特殊的失敗標記NotFound
。
測試程式樣例 (C語言版)##
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 10 #define NotFound 0 typedef int ElementType; typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 儲存線性表中最後一個元素的位置 */ }; List ReadInput(); /* 裁判實現,細節不表。元素從下標1開始儲存 */ Position BinarySearch( List L, ElementType X ); int main() { List L; ElementType X; Position P; L = ReadInput(); scanf("%d", &X); P = BinarySearch( L, X ); printf("%d\n", P); return 0; } /* 你的程式碼將被嵌在這裡 */
輸入樣例1:
5
12 31 55 89 101
31
輸出樣例1:
2
輸入樣例2:
3
26 78 233
31
輸出樣例2:
0
程式程式碼:
Position BinarySearch( List Tbl, ElementType K ) { if(Tbl==NULL) return NotFound; int low=1,high=Tbl->Last; int mid; while(low<=high)//low一定小於等於high 如下標為1、2、3 要查詢的是下標為1的數,第一次是比較下標為2的數,不符合 high就變成了1,如果寫low<high就會返回錯誤的結果 { mid=(low+high)/2; if(Tbl->Data[mid]==K) return mid; else if(Tbl->Data[mid]>K) high=mid-1; else low=mid+1; } return NotFound; }
##測試結果與題目裁判結果相符
##二分查詢總結:
-
概念
二分查詢也稱折半查詢(Binary Search),它是一種效率較高的查詢方法。但是,折半查詢要求線性表必須採用順序儲存結構,而且表中元素按關鍵字有序排列。該演算法充分利用了元素間的次序關係,採用分治策略,可在最壞的情況下用O(log n)完成搜尋任務。它的基本思想是,將n個元素分成個數大致相同的兩半,取a[n/2]與欲查詢的x作比較,如果x=a[n/2]則找到x,演算法終止。如 果x小於a[n/2],則我們只要在陣列a的左半部繼續搜尋x(這裡假設陣列元素呈升序排列)。如果x大於a[n/2],則我們只要在陣列a的右 半部繼續搜尋x。
-
查詢過程
首先,假設表中元素是按升序排列,將表中間位置記錄的關鍵字與查詢關鍵字比較,如果兩者相等,則查詢成功;否則利用中間位置記錄將表分成前、後兩個子表,如果中間位置記錄的關鍵字大於查詢關鍵字,則進一步查詢前一子表,否則進一步查詢後一子表。重複以上過程,直到找到滿足條件的記錄,使查詢成功,或直到子表不存在為止,此時查詢不成功。 -
演算法要求
1、線性表必須採用順序儲存結構
2、表中元素按照關鍵字有序排列(升序或者降序) -
比較次數
計算公式:
當順序表有n個關鍵字時:
查詢失敗時,至少比較a次關鍵字;查詢成功時,最多比較關鍵字次數是b。
注意:a,b,n均為正整數。 -
Python原始碼
def bin_search(data_list, val):
low = 0 # 最小數下標
high = len(data_list) - 1 # 最大數下標
while low <= high:
mid = (low + high) // 2 # 中間數下標
if data_list[mid] == val: # 如果中間數下標等於val, 返回
return mid
elif data_list[mid] > val: # 如果val在中間數左邊, 移動high下標
high = mid - 1
else: # 如果val在中間數右邊, 移動low下標
low = mid + 1
return # val不存在, 返回None
ret = bin_search(list(range(1, 10)), 3)
print(ret)
- C/C++遞迴實現
#include<iostream>
using namespace std;
int a[100]={1,2,3,5,12,12,12,15,29,55};//陣列中的數(由小到大)
int k;//要找的數字
int found(int x,int y)
{
int m=x+(y-x)/2;
if(x>y)//查詢完畢沒有找到答案,返回-1
return -1;
else
{
if(a[m]==k)
return m;//找到!返回位置.
else if(a[m]>k)
return found(x,m-1);//找左邊
else
return found(m+1,y);//找右邊
}
}
int main()
{
cin>>k;//輸入要找的數字c語言把cin換為scanf即可
cout<<found(0,9);//從陣列a[0]到a[9]c語言把cout換為printf即可
return 0;
}
##函式執行時間計時程式模板
#include <iostream>
#include <time.h> //For using the system Timer
#include <stdlib.h>
using namespace std;
clock_t start, stop; //Define the start and stop of the timer
int PrintN(int n)
{
int i = 0;
for (i; i < n; i++) {
std::cout << i << endl;
}
return 0;
}
int main()
{
int n;
std::cin>>n;
start = clock();
PrintN(n);
stop = clock();
double duration = ((double)(stop - start)) / CLK_TCK; //To calculate the time that this function used
std::cout << duration << endl;
system("PAUSE"); //Pause the system for a moment
return 0;
}