1. 程式人生 > >資料結構與演算法基礎-02-二分查詢-實踐

資料結構與演算法基礎-02-二分查詢-實踐


演算法中查詢演算法排序演算法可謂是最重要的兩種演算法,是其他高階演算法的基礎。在此係列文章中,將逐一學習和總結這兩種基礎演算法中常見的演算法實現。首先,第一種演算法——二分(折半)查詢的學習和練習。


1、概念

二分查詢,是逐次將查詢範圍折半縮小搜尋的範圍直到找到那個需要的結果。它是一種效率較高的查詢演算法,但是要使用它來完成查詢任務,有一個前提,那就是所要搜尋的範圍的資料結構是採用線性儲存結構的線性表,且它已經將資料排好序,常見的有陣列,下文以陣列為例進行說明。

2、演算法思想

每次取陣列中間位置的值與需要查詢的值比較,如果中間位置的值比需要查詢的值大,則在陣列前半部分迴圈這個查詢的過程;如果中間位置的值比需要查詢的值小,則在陣列後半部分迴圈這個查詢的過程。直到查詢到了為止,否則陣列中沒有需要查詢的值。

【注意】因為需要確定每次查詢的區間範圍,所以我們用pow表示區間的上界序號,low表示區間的下界序號,middle表示中間位置序號。

程式碼:


#include <iostream>
#define NotFound -1

using namespace std;

/* To get the length of the objective array[] */
int get_array_len(int array[] ){
    int len =0;
    len =(sizeof(array) / sizeof(array[0]));
    if (len <= 0 ){
        std::cout << "error"<< endl;
        return -1;
    }
    return len;
}


int binarySearch( int a[],int value)
{
    int low = 0;
    int middle = 0;               //定義區間下界並初始化為0,宣告中間位置變數middle
    int len = get_array_len(a);          //計算陣列長度,返回長度len
    if (len == -1){
        return -1;
    }
    int high = len;               //上界high,初值為len
    if(a == NULL){
        return NotFound;
    }                           //如果陣列為空,結束操作,返回-1

    while(low <= high)
    {
        if (value > a[high]){
            return NotFound;
        }
        middle = (low+high) /2;     //為middle開始賦予初值
        if(a[middle] == value)      //先判斷middle所在處的值是不是需要查詢的值
            return middle;         //返回查詢到的目標值序號
        else if(a[middle] > value)    //若middle處的值大於需要查詢的值,則將搜尋範圍縮小到前半部分
            high = middle - 1;
        else
            low = middle + 1;      //若middle處的值小於需要查詢的值,則將搜尋範圍縮小到後半部分
    }
    return NotFound;               //若循壞結束,即high<low,說明需要查詢的值不存在,則返回x查詢失敗標誌-1
}

/* check the input number */

int input_check (){
    int num;
    cout<<"請輸入A/B中元素個數:"<<endl;
    cin>>num;
    bool flag = false;       //判斷標誌位,如果r輸入數大於100000,標誌位置置false
    while (!flag){                     //依題意,元素個數應小於1000000
        if(num >1000000){
            cout<<"元素個數應小於1000000,請重新輸入:"<<endl;
            cin>>num;
            flag = false;         //大於100000false
        }
        else{
            flag = true;
        }
    }
    return num;
}

int main()
{

    int n = 0,m = 0;   //從鍵盤錄入A,B兩個集合中的元素個數
    n = input_check();    //從鍵盤讀入n並判斷其是否符合要求
    m = input_check();

    int *a = new int[n];  //建立動態陣列-A集合
    int *b = new int[m]; //建立動態陣列-B集合
    int *list = new int[m<=n? m: n]; //定義一個List來存放A,B中相同的元素


    for(int i = 0;i<n;i++){     //給A中每個元素賦值
        cout<<"A中元素值:"<<endl;
        cin>>a[i];
    }
    int* p = NULL;
    p = list;

    for(int i=0;i<m;i++){
            cout<<"B中元素值:"<<endl;
            cin>>b[i];
            int result = binarySearch(a, b[i]); //對輸入的每個B陣列元素,在A中進行二分查詢,並將查詢結果返回至result
            if(result != -1) {       //判斷返回結果,若結果不為-1,則說明查詢成功,即A中有此元素,將此元素加入list中
                *p = a[result];
                p++;
                cout<<result<<"   "<<a[result]<<endl;
            }
    }

    int len_list = get_array_len(list);
    cout<<"A,B中相同的元素個數為:"<<len_list+1<<endl;
    for(int i = 0; i<= len_list; i++){  //將結果打印出來
        cout<<list[i]<<endl;

    }
    delete [] a;
    delete [] b;
    return 0;
}

3、總結:

二分查詢是一種效率較高的演算法,但是需要給定的數列是有序的。可以結合之後的排序演算法一起使用。