基礎:查找的基本概念
查找表:由同一類數據元素構成的集合。(線性表、數表、散列表)
關鍵字:是數據元素中某個數據項的值,用它可以表示一個數據元素。(主關鍵字:唯一地標識;次關鍵字:不唯一地標識)
查找:根據制定的某個值,在查找表中確定一個其關鍵字等於給定的這個值的數據元素
動態/靜態查找:查表的同時改表成為動態查找,反之為靜態查找
平均查找長度:ASL=∑PiCi (i=1,2,3,…,n),Pi 為查找表中第i個數據元素的概率,Ci為找到第i個數據元素時已經比較過的次數。
*線性表的查找*
(1)順序查找
(2)二分查找(折半查找)
(3)分塊查找
(1)順序查找
從表的一端開始,依次將記錄的關鍵字與給定的值進行比較。
順序查找既適用於順序存儲結構(數組),又適用於鏈式存儲結構(鏈表),以下介紹順序存儲結構:
數據元素的類型:
1 typedef struct{ 2 KeyType key; 3 InfoType otherinfo 4 }ElemType
1 typedef struct { 2 ElemType *R; //表基址
3 int length; //表長
4 }SSTable;
代碼:
1 int LocateELem(SqList L,ElemType e) 2 { for (i=0;i< L.length;i++) 3 if (L.elem[i]==e) return i+1; 4 return 0; 5 }
改進:把待查關鍵字key存入表頭(“哨兵”),從后向前逐個比較,可免去查找過程中每一步都要檢測是否查找完畢,加快速度。
1 int Search_Seq( SSTable ST , KeyType key ){ 2 //若成功返回其位置信息,否則返回0
3 ST.R[0].key =key; 4 for( i=ST.length; ST.R[ i ].key!=key; - - i ); 5 //不用for(i=n; i>0; - -i) 或 for(i=1; i<=n; i++)
6 return i; 7 }
順序查找的性能分析:
空間復雜度:一個輔助空間。
時間復雜度:
1) 查找成功時的平均查找長度 設表中各記錄查找概率相等 ASLs(n)=(1+2+ ... +n)/n =(n+1)/2
2)查找不成功時的平均查找長度 ASLf =n+1
(2)二分查找
例:找“21”:

若k==R[mid].key,查找成功
若k<R[mid].key,則high=mid-1
若k>R[mid].key,則low=mid+1
代碼:(迭代)
1 int Search_Bin(SSTable ST,KeyType key){ 2 low=1;high=ST.length;//若找到,則函數值為該元素在表中的位置,否則為0 3 while(low<=high){ 4 mid=(low+high)/2; 5 if(key==ST.R[mid].key) return mid; 6 else if(key<ST.R[mid].key) high=mid-1;//前一子表查找 7 else low=mid+1; //后一子表查找 8 } 9 return 0; //表中不存在待查元素 10 }
*需要特別注意的是循環執行的條件是:low<=high,而不是low<high,因為low=high時,還要比較最后一個元素。
代碼:(遞歸)
1 int Search_Bin (SSTable ST, keyType key, int low, int high) 2 { 3 if(low>high) return 0; //查找不到時返回0
4 mid=(low+high)/2; 5 if(key等於ST.elem[mid].key) return mid; 6 else if(key小於ST.elem[mid].key) 7 ……..//遞歸
8 else……. //遞歸
9 }
二分查找的性能分析——判定樹


若所有結點的空指針域設置為一個指向一個方形結點的指針,稱方形結點為判定樹的外部結點;對應的,圓形結點為內部結點。
查找成功時的平均查找長度:ASL=1/11*(1*1+2×2+4×3+4*4 )=33/11=3
查找成功時比較次數:為該結點在判定樹上的層次數,不超過樹的深度 d = [log2n] + 1 查找不成功的過程就是走了一條從根結點到外部結點的路徑d或d-1。
二分查找的性能分析:
查找過程:每次將待查記錄所在區間縮小一半,比順序查找效率高,時間復雜度O(log2 n)
適用條件:采用順序存儲結構的有序表,不宜用於鏈式結構
(3)分塊查找
分塊有序,即分成若干子表,要求每個子表中的數值都比后一塊中數值小(但子表內部未必有序)。 然后將各子表中的最大關鍵字構成一個索引表,表中還要包含每個子表的起始地址(即頭指針)。

① 對索引表使用折半查找法(因為索引表是有序表);
② 確定了待查關鍵字所在的子表后,在子表內采用順序查找法(因為各子表內部是無序表);
查找效率:ASL=Lb+Lw(Lb:對索引表查找的ASL;Lw:對塊內查找的ASL)
分塊查找的性能分析:
優點:插入和刪除比較容易,無需進行大量移動。
缺點:要增加一個索引表的存儲空間並對初始索引表進行排序運算。
適用情況:如果線性表既要快速查找又經常動態變化,則可采用分塊查找。
