順序查詢與 哨兵 的使用 二分查詢

2021-09-10 16:48:01 字數 4065 閱讀 3572

陣列構成:

typedef struct lnode *list;

struct lnodelnode;

一. 順序查詢

由於不帶「哨兵」,陣列的第乙個位置(data[0])用於儲存資料,所以線性表的初始化中last是從-1開始的,表示表中暫無元素。

/*初始化1

*實現功能:建立空的線性表

*傳入形參:無

*返回值:線性表指標

*/list makeempty1()

相對應的查詢函式如下:

/*順序查詢  (無"哨兵")

*函式功能:在data[0]~data[n]中查詢關鍵字為x的資料元素

*傳入形參:線性表指標 ptrl, 關鍵字 x

*返回值:查詢成功返回所在單元下標,不成功返回 0

所謂「哨兵」就是用乙個特殊值來作為陣列的邊界,使用「哨兵」可以少用一條判斷語句,所以可以提高程式的效率。

這樣就可以將陣列的第乙個位置作為「哨位」,資料的儲存從data[1]開始。因此線性表的初始化中last是從0開始的,表示表中暫無元素。

/*初始化2

*實現功能:建立空的線性表

*傳入形參:無

*返回值:線性表指標

*/list makeempty2()

相對應的查詢函式如下:

/*順序查詢 (有"哨兵") 

*函式功能:在data[1]~data[n]中查詢關鍵字為x的資料元素

*傳入形參:線性表指標 ptrl, 關鍵字 x

*返回值:查詢成功返回所在單元下標,不成功返回 0

*/int sequentialsearch2(list ptrl,elementtype x)

將哨兵賦值為關鍵字x,這樣判別條件便只有乙個。並且同樣當檢索完的時候,會滿足判別條件並返回「0」。

二. 二分查詢(帶哨兵)

二分查詢,所針對的是有序陣列,即資料在之前必須已經由小到大排序完成。

簡單來說即通過尋找中間數並比較大小,確定目標數所在區間,並且不斷通過這種方法縮小區間,直到找到目標數。

具體實現如下:

1. 通過last確定左(left)右(right)邊界,計算得出中間數字置(mid)。

2. 比較mid處的數與目標數x的大小,確定目標數所在區間(左半部分或右半部分或者該處就是x)。

3. (1)若x在左半部分,則將右邊界right左移到mid的左邊。再重新確定mid,重複1,2步驟。

(2)若x在右半部分,則將左邊界left左移到mid的右邊。再重新確定mid,重複1,2步驟。

(3)若x即為mid處的數,則返回mid的值。

該方法與「最大子列和」問題中「分而治之」的方法,有著異曲同工之妙。不同的是,在這個問題中,我們只需要要找到目標數的位置即可,所以通過「分」之後不需要兩邊都「治」,另一半部分直接捨棄。這樣做較之順序查詢的方法便可大大增加查詢效率。

下面通過乙個例子來說明:

假如要從下面的陣列中找數「55」

1. mid = (left + right)/2 = 14/2 = 7,此時mid位置上的數為 88 > 55. 55在左半部分,所以right = mid -1 = 6。

2. mid = (left + right)/2 = 7/2 = 3,此時mid位置上的數為34 < 55. 55在右半部分,所以left = mid + 1 = 4。

3. mid = (left + right)/2 = 10/2 = 5,此時mid位置上的數為68 > 55. 55在左半部分,所以right = mid - 1 = 4。

4. mid = (left + right)/2 = 8/2 = 4,此時mid位置上的數為55.成功找到目標數55的位置,返回mid的值。

那如果查詢的數不在該陣列內時,情況會如何呢?

如上例中如果我們要找的目標數為「42」,當進行到3時,mid位置上的數為55 > 42.

程式會判定42在左半部分,所以更改右邊界right的值,right = mid - 1 = 3

此時,left = 4;right = 3;右邊界(right)到了左邊界(left)的左邊,說明查詢完畢。沒找到42,返回 -1。

由此我們便可以知道,迴圈的截至條件為 left > right。

程式如下:

/*二分查詢 (有"哨兵") 

*函式功能:在data[1]~data[n]中查詢關鍵字為x的資料元素

*傳入形參:線性表指標 ptrl, 關鍵字 x

*返回值:查詢成功返回所在單元下標,不成功返回 -1

*/int binarysearch(list ptrl,elementtype x)

return nofound;

}

測試主函式如下:

#include #include #define maxsize 100

typedef int elementtype;

typedef struct lnode *list;

struct lnodelnode;

int sequentialsearch1(list ptrl,elementtype x);

int sequentialsearch2(list ptrl,elementtype x);

list makeempty1();

list makeempty2();

int binarysearch(list ptrl,elementtype x);

int main()

while(1);

printf("輸入查詢的數:");

scanf("%d",&x);

printf("position:%d\n",sequentialsearch1(l,x));

free(l);

getch();

l = makeempty2();//帶哨兵的初始化

printf("輸入元素(遞增輸入):");

dowhile(1);

printf("帶哨兵的順序查詢\n");

printf("輸入查詢的數:");

scanf("%d",&x);

printf("position:%d\n",sequentialsearch1(l,x));

printf("二分查詢\n");

printf("輸入查詢的數:");

scanf("%d",&x);

printf("position:%d",binarysearch(l,x));

free(l);

}

測試結果如下:

測試環境:win10  使用軟體:dev_c++

順序查詢與二分查詢

先上 include void printarr int a,int n void bublesort int a,int n void swap int a,int b int binarysearch int a,int n,int k int normalsearch int a,int n,...

順序查詢 二分查詢

順序查詢 適用範圍 沒有進行排序的資料序列 缺點 速度非常慢,效率為o n cpp view plain copy 在code上檢視 片派生到我的 片 實現 template type sequencesearch type begin,type end,const type searchvalue...

順序查詢與二分查詢解析

非常簡單 示例1 在成績中查詢分數是100的第乙個分數 99 86 59 63 49 100 99 78 for int i 0 i示例2 在學生中查詢分數是100的第乙個學生 儲存結構可以是順序表,也可以是鍊錶。逐個比較查詢,如果找到,返回資料或者索引,如果到最後也沒有找到,返回null 可以是在...