數算---數據查找

順序查找

順序查找(Sequential Search),又稱為線性查找。是最基本的查找技術,它的查找過程,從表中的第一個(或最后一個)記錄開始,逐個進行記錄關鍵字和給定值比較。若某個記錄的關鍵字和給定值相等,說明查找成功,如果直到最后一個(或第一個)記錄,沒有關鍵字與給定值相等,說明查找不成功。

//a為數組,n為查找的數組個數,key為要查找的關鍵字;
int Sequential_Search(int *a,int n,int key){
    for (int i = 0; i <= n - 1 ; i++)
        if (a[i] == key)
            return i;
   //沒找到返回-1
    return -1;
}
折半查找

折半查找(Binary Search)技術,又稱二分查找。
前提條件是線性表中的記錄必須是關鍵碼有序的(通常從小到大有序),線性表必須采用順序存儲。
基本思想:

  • 在有序表中,取中間記錄作為比較對象,若給定值與中間記錄的關鍵字相等則查找成功。
  • 若給定值小于中間記錄關鍵字,則在中間記錄的左半區繼續查找。
  • 若給定值大于中間記錄關鍵字,則在中間記錄的右半區繼續查找。
  • 重復以上操作,直到查找成功,或者查找結束還未找到即查找失敗。
//假設數組a,已經是有序的(從小到大)
int Binary_Search(int *a,int n,int key){
    
    int low,high,mid;
    //定義最低下標為記錄首位
    low = 0;
    //定義最高下標為記錄末位
    high = n - 1;
    while (low <= high) {
        
        //折半計算
        mid = (low + high) /2;
        
        
        if (key < a[mid]) {
            //若key比a[mid] 小,則將最高下標調整到中位下標小一位;
            high = mid-1;
        }else if(key > a[mid]){
             //若key比a[mid] 大,則將最低下標調整到中位下標大一位;
            low = mid+1;
        }else
            //若相等則說明mid即為查找到的位置;
            return mid;
    }
    
    return 0;
}

折半查找優化
折半查找公式為mid = (low + high) / 2 = low + 1/2 (high - low)
考慮將1/2進行改進,方案如下:

假設,a[11] = {0, 1, 16, 24, 35, 47, 59, 62, 73, 88, 99} , low = 0, high = 10, 則 a[0] = 0, a[10] = 99, 如果需要查找key = 16,按照常規折半查找需要進行4次才能找到結果,但是如果用新的共識,則


對2.616取整,則mid = 2,那么我們只需要進行2次就能找到結果。

我們稱優化后的方法為插值查找(Interpolation Search),是根據查找的關鍵字key與查找表中的最大最小記錄的關鍵字比較后的查找方法,核心在于mid的計算公式關鍵部分:

//插值查找
int Interpolation_Search(int *a,int n,int key){
    int low,high,mid;
    low = 1;
    high = n;
    
    while (low <= high) {
        
        //插值
        mid = low+ (high-low)*(key-a[low])/(a[high]-a[low]);
    
        if (key < a[mid]) {
            //若key比a[mid]插值小,則將最高下標調整到插值下標小一位;
            high = mid-1;
        }else if(key > a[mid]){
            //若key比a[mid]插值 大,則將最低下標調整到插值下標大一位;
            low = mid+1;
        }else
            //若相等則說明mid即為查找到的位置;
            return mid;
    }
    
    return 0;
}
斐波拉契查找

斐波拉契查找(Fibonacci Search)是利用斐波拉契數列為查找的下標數組,而不是折半查找中根據搜索數組下標來查找,說白了就是利用斐波拉契數列來生成新的mid。

例如下面F為斐波拉契數列,a為要查找的記錄數組,長度為10,low = 1, high = 10, 給定值key = 99,查找a中是否有99,返回相應的下標:


計算過程:

  1. 由于n = 10, key = 99,F[6] < n < F[7],得到k = 7, 因為F[7] = 13, 而a最大僅有a[10], 后面的a[11],a[12] 是為賦值的,為了避免之后的數值比對數組越界問題,需要將后續的2個元素賦值,a[11] = a[12] = 99。


  2. 此時mid = low + F[k - 1] - 1 = 1 + F[7 - 1] - 1 = 1 + 8 -1 = 8;
    key > a[8] ---> 99 > 73;
    low = mid + 1 = 8 + 1 = 9;
    k = k - 2 = 7 - 2 = 5;


  3. mid = low + F[k - 1] - 1 = 1 + F[5 - 1] - 1 = 9 + 3 - 1 = 11;
    key = a[11] ---> 99 = 99;
    mid >n , 11 > 10, 則返回n,返回10.
    表示找到key= 99是在數組a中的位置是10的位置上。

key = 99是處在邊緣的值,我們可以假設key = 59,來看看在a數組中間的數值計算過程又是怎樣的?


計算過程:

  1. n = 10, 同上面一樣,得到k = 7, F[7] = 13, 補齊后兩位數值為a[11] = a[12] = a[10] = 99;

  2. mid = low + F[k - 1] - 1 = 1 + F[7 - 1] - 1=1 + 8 - 1 = 8;
    key < a[8] ---> 59 < 73;
    high = mid - 1 = 8 - 1 = 7;
    k = k - 1 = 6;


  3. mid = low + F[k - 1] = 1 + F[6 - 1] - 1 = 1 + 5 -1 = 5;
    key > a[5] ---> 59 > 47;
    low = mid + 1 = 5 + 1 = 6;
    k = k - 2 = 4;


  4. mid = low +F[k - 1] - 1 = 6 + F[4 - 1] - 1 = 7;
    key < a[7] ---> 59 < 62
    high = mid - 1 = 6;
    k = k - 1 = 3;


  5. mid = low + F[k - 1] - 1 = 6 + 1 - 1 = 6;
    key = a[6];
    mid < n ; 6 < 10, 返回 6;
    找到key = 59在數組a中的位置為6。

結論:斐波拉契查找就是利用mid = low + F[k -1] - 1 這個公式來計算出mid的所在位置。然后比較給定值與a[mid]的大小,然后繼續或結束。

int F[100]; /* 斐波那契數列 */
//初始化數列
    F[0]=0;
    F[1]=1;
    for(i = 2;i < 100;i++)
    {
        F[i] = F[i-1] + F[i-2];
    }

//計算過程
int Fibonacci_Search(int *a,int n,int key){
  
    int low,high,mid,i,k;
    //最低下標為記錄的首位;
    low = 1;
    //最高下標為記錄的末位;
    high = n;
    k = 0;
    
    //1.計算n為斐波拉契數列的位置;
    while (n > F[k]-1) {
        k++;
    }
    
    //2.將數組a不滿的位置補全值;
    for(i = n;i < F[k]-1;i++)
        a[i] = a[n];
    
    //3.
    while (low <= high) {
        
        //計算當前分隔的下標;
        mid = low+F[k-1]-1;
        
        
        if (key < a[mid]) {
            //若查找的記錄小于當前分隔記錄;
            //將最高下標調整到分隔下標mid-1處;
            high = mid-1;
            //斐波拉契數列下標減1位;
            k = k-1;
            
        }else if(key > a[mid]){
            //若查找的記錄大于當前的分隔記錄;
            //最低下標調整到分隔下標mid+1處
            low = mid+1;
            //斐波拉契數列下標減2位;
            k = k-2;
            
        }else{
            if (mid <= n) {
                //若相等則說明,mid即為查找的位置;
                return mid;
            }else
            {
                //若mid>n,說明是補全數值,返回n;
                return n;
            }
        }
    }
    return 0;
}
總結

綜上幾種數據查找的方法,說白了就是對mid的計算公式的不同,從而達到不同的效率。


?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容

  • 順序表查找 試想一下,要在散落的一大堆書中找到你需要的那本有多么麻煩。碰到這種情況的人大都會考慮做一件事,那就是把...
    Joker_King閱讀 650評論 0 0
  • 一、查找表1、定義A.查找表(table):由同一類型的數據元素(或記錄)構成的集合,由于“集合”中的數據元素間存...
    Qi0907閱讀 1,007評論 0 0
  • 靜態查找表(Static Search Table):只作查找操作的查找表 散列查找:直接查到儲存的位置 數據[1...
    張天宇_bba7閱讀 198評論 0 0
  • 目錄一.查找概論1.概念:2.查找表按照操作方式來分有兩大種:靜態查找表和動態查找表3.面向查找操作的數據結構稱為...
    Movle閱讀 401評論 0 1
  • 查找 查找表是由同一類型的數據元素(或記錄)構成的集合。關鍵字是數據元素中某個數據項的值,也稱為鍵值,用它可以標識...
    keeeeeenon閱讀 2,001評論 0 3