数据结构50:二分查找法(折半查找法)
生活随笔
收集整理的這篇文章主要介紹了
数据结构50:二分查找法(折半查找法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
折半查找,也稱二分查找,在某些情況下相比于順序查找,使用折半查找算法的效率更高。但是該算法的使用的前提是靜態查找表中的數據必須是有序的。
例如,在{5,21,13,19,37,75,56,64,88 ,80,92}這個查找表使用折半查找算法查找數據之前,需要首先對該表中的數據按照所查的關鍵字進行排序:{5,13,19,21,37,56,64,75,80,88,92}。在折半查找之前對查找表按照所查的關鍵字進行排序的意思是:若查找表中存儲的數據元素含有多個關鍵字時,使用哪種關鍵字做折半查找,就需要提前以該關鍵字對所有數據進行排序。
折半查找算法
對靜態查找表{5,13,19,21,37,56,64,75,80,88,92}采用折半查找算法查找關鍵字為 21 的過程為:圖 1 折半查找的過程(a)
如上圖 1 所示,指針 low 和 high 分別指向查找表的第一個關鍵字和最后一個關鍵字,指針 mid 指向處于 low 和 high 指針中間位置的關鍵字。在查找的過程中每次都同 mid 指向的關鍵字進行比較,由于整個表中的數據是有序的,因此在比較之后就可以知道要查找的關鍵字的大致位置。
例如在查找關鍵字 21 時,首先同 56 作比較,由于21 < 56,而且這個查找表是按照升序進行排序的,所以可以判定如果靜態查找表中有 21 這個關鍵字,就一定存在于 low 和 mid 指向的區域中間。
因此,再次遍歷時需要更新 high 指針和 mid 指針的位置,令 high 指針移動到 mid 指針的左側一個位置上,同時令 mid 重新指向 low 指針和 high 指針的中間位置。如圖 2 所示:
圖 2 折半查找的過程(b)
? 同樣,用 21 同 mid 指針指向的 19 作比較,19 < 21,所以可以判定 21 如果存在,肯定處于 mid 和 high 指向的區域中。所以令 low 指向 mid 右側一個位置上,同時更新 mid 的位置。
圖 3 折半查找的過程(3) 當第三次做判斷時,發現 mid 就是關鍵字 21 ,查找結束。
注意:在做查找的過程中,如果 low 指針和 high 指針的中間位置在計算時位于兩個關鍵字中間,即求得 mid 的位置不是整數,需要統一做取整操作。
折半查找的實現代碼: #include <stdio.h> #include <stdlib.h> #define keyType inttypedef struct
{keyType key; // 查找表中每個數據元素的值// 如果需要,還可以添加其他屬性 }ElemType;typedef struct
{ElemType *elem; // 存放查找表中數據元素的數組int length; // 記錄查找表中數據的總數量 }SSTable;
// 創建查找表 void Create(SSTable **st, int length)
{(*st) = (SSTable*)malloc(sizeof(SSTable));(*st)->length = length;printf("輸入表中的數據元素:\n");// 根據查找表中數據元素的總長度,在存儲時,從數組下標為 1 的空間開始存儲數據for (int i=1; i<=length; i++)
{scanf("%d", &((*st)->elem[i].key));} }
//折半查找算法 int Search_Bin(SSTable *ST, keyType key)
{int low = 1; //初始狀態 low 指針指向第一個關鍵字int high = ST->length; //high 指向最后一個關鍵字int mid;while (low <= high)
{mid = (low+high) / 2; // int 本身為整形,所以,mid 每次為取整的整數if (ST->elem[mid].key == key) // 如果 mid 指向的同要查找的相等,返回 mid 所指向的位置 {return mid;}
else if(ST->elem[mid].key > key) // 如果mid指向的關鍵字較大,則更新 high 指針的位置 {high = mid-1;}// 反之,則更新 low 指針的位置else
{low = mid + 1;}}
return 0; }int main(int argc, const char * argv[])
{SSTable *st;Create(&st, 11);getchar();printf("請輸入查找數據的關鍵字:\n");int key;scanf("%d", &key);int location = Search_Bin(st, key);//如果返回值為 0,則證明查找表中未查到 key 值,if (location == 0)
{printf("查找表中無該元素");}
else
{printf("數據在查找表中的位置為:%d", location);}return 0; }
以圖 1 的查找表為例,運行結果為: 輸入表中的數據元素: 5 13 19 21 37 56 64 75 80 88 92 請輸入查找數據的關鍵字: 21 數據在查找表中的位置為:4
?
折半查找的性能分析
折半查找的運行過程可以用二叉樹來描述,這棵樹通常稱為“判定樹”。例如圖 1 中的靜態查找表中做折半查找的過程,對應的判定樹如圖 4:圖 4 折半查找對應的判定樹
在判定樹中可以看到,如果想在查找表中查找 21 的位置,只需要進行 3 次比較,依次和 56、19、21 進行比較,而比較的次數恰好是該關鍵字所在判定樹中的層次(關鍵字 21 在判定樹中的第 3 層)。
對于具有 n 個結點(查找表中含有 n 個關鍵字)的判定樹,它的層次數至多為:log2n + 1(如果結果不是整數,則做取整操作,例如:?log211 +1 = 3 + 1 = 4?)。
同時,在查找表中各個關鍵字被查找概率相同的情況下,折半查找的平均查找長度為:ASL = log2(n+1) – 1。
總結
通過比較折半查找的平均查找長度,同前面介紹的順序查找相對比,明顯折半查找的效率要高。但是折半查找算法只適用于有序表,同時僅限于查找表用順序存儲結構表示。當查找表使用鏈式存儲結構表示時,折半查找算法無法有效地進行比較操作(排序和查找操作的實現都異常繁瑣)。
轉載于:https://www.cnblogs.com/ciyeer/p/9065781.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的数据结构50:二分查找法(折半查找法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么用腾讯元宝进行风险预测?
- 下一篇: 5-21