數據結構:靜態查找表


 數據結構:靜態查找表(C語言版) 

1.寫在前面

  從查找說起:

    在英漢字典中查找某個英文單詞的中文解釋;在新華字典中查找某個漢字的讀音、含義;在對數表、平方根表中查找某個數的對數、平方根;郵遞員送信件要按收件人的地址確定位置等等。
    從計算機、計算機網絡中查找特定的信息,就需要在計算機中存儲包含該特定信息的表。查找是許多程序中最消耗時間的一部分。因而,一個好的查找方法會大大提高運行速度。

  ►先討論靜態查找表:

    靜態查找表應該是查找中最為簡單的。僅僅是在固定的表中對元素的查找,而不涉及修改表中的元素

    我們討論的是 在無序表、順序表中的遍歷查找和快速的折半查找

2.代碼分解

  ►無序表上的順序查找     

  方式:從查找表的一端依序與表中的元素進行比較。

  

  代碼是很簡單的,直接給出,以便后續分析:

#include <iostream>
typedef int KeyType;

typedef  struct {
    KeyType  key;
    int  info;
}ElemType;

typedef  struct {
    ElemType  *elem;     // 數據元素存儲空間基址,建表時
    int       length;    // 表的長度
} SSTable;


int  Sq_search(SSTable ST, KeyType key) {
    // 在無序表中查找元素key,查找成功時,返回元素在表中的位置 ,否則返回0
    int i=ST.length;
    while (i>=1&&ST.elem[i].key!=key) i--;
    return i;
}

int Init_search(SSTable &ST,int length)//初始化表
{
    ST.length=length;
    ST.elem = (ElemType *)malloc(sizeof(ElemType)*(length+1));
}

int Creat_search(SSTable &ST,int length)//創建表
{
    ElemType *ptr = ST.elem;
    int temp =0;
    int i=0;
    ptr++; //我們將第一個元素空出來!
    while (temp!=-1&&(i++)<length)
    {
        scanf("%d",&temp);
        ptr++->key=temp;
    }
}

int main() {
    SSTable table;
    Init_search(table,5);
    Creat_search(table,5);
    printf("已經找到位置:%d",Sq_search(table, 13));
    return 0;
}

說明:
  請注意,我們在0號位置留空,在這里僅僅是為了直觀顯示索引位置

  ►設置監視哨

    但是我們還可以優化這段代碼,那就是設置監視哨。

  所謂監視哨,就是將空出來的下標為0的這個元素的值設為Key.   

分析:

  這樣我們就不用多次判斷i是否越界,因為就算靜態表中找不到,也會在0位置上配對成功,返回0!

    while (i>=1&&ST.elem[i].key!=key) i--;
      改為:
    ST.elem[0].key = key; //監視哨:下標為0的位置存放待查找的元素
    while (ST.elem[i].key!=key)

  我們來分析一下算法復雜度:

    

  ►有序表上的順序查找  

    方式:在有序表上查找的時候,我們可以對無序查找進行優化:

   int   i = ST.length;  
   ST.elem[0].key = key; 
   while   (key < ST.elem[i].key)    i--;
   if  (key == ST.elem[i].key)
       return   i;
   return 0

    即當ST.elem[i].key<= ST.elem[0].key 的時候我們就停止查找!
    為什么呢?因為ST.elem[i].key<= ST.elem[0].key的時候是兩種可能,要么小於,既然<就無須再比了,要是=也就得出結果了!

  ►有序表上的折半查找     

方法:

  我們把要查找的值x與數組的中間值mid進行比較,如果說x<mid,那么因為數組有序,mid右邊的數字都會大於x,所以去mid右邊查找是徒勞的。此時我們僅僅需要去mid左邊查找即可!同理我們把mid左邊也看成是一個數組,我們就可以重復上述操作了!

  總之,先確定待查記錄所在的范圍(區間),若待查記錄等於表中間位置上的記錄,則查找成功;否則,縮小查找范圍,即若待查記錄小於中間位置上的元素,則下一次到前半區間進行查找,若待查記錄大於中間位置上的元素,則下一次到后半區間進行查找。

  

  核心代碼如下:

while (low<=high)   {
      int mid= low + [(high-low)/2];
      if (ST.elem[mid].key==key) return mid;        //查找成功
      else  if  (key < ST.elem[mid].key) high=mid-1; //下一次到前半區間查找
              else low=mid+1;                 //下一次到后半區間查找 
}

  我們分析一下這個結束條件: while(low<=high)

    當low=high的時候,我們已經可以確定這是能夠進行比較的最后一個元素了,因為此時不可能再對數組進行左右划分!
    如果此時,mid元素不等於Key的話,可以判定查找失敗!

  若此時mid<key,low+1就會大於hi
  若此時mid>key,hi-1就會小與low

  所以自然就會結束循環!

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM