尋找演算法的研究

來源:互聯網
上載者:User

1.      順序尋找

順序尋找就是從序列的第一個元素開始,從頭到尾逐個尋找,直到找到所需的資料或搜尋完整個序列。

程式設計如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

int search(int *,int,int);

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x;

       printf("請輸入10個數字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("\n");

       printf("請輸入要尋找的數:\n");

       scanf("%d",&x);

       n=search(a,10,x);

       if(n<=0)

       {

              printf("沒有找到你想找得數!");

       }

       else

       {

              printf("你想找的數 %d 在數列的第 %d 個位置。",x,n);

       }

       return0;

}

int search(int *a,int num,int value)

{

       intresult=0;

       inti;

       for(i=0;i<num;i++)

       {

              if(value==a[i])

              {

                     result=i+1;

                     break;

              }

       }

       return(result);

}

2.      折半尋找

折半尋找是將有序數列不斷的縮小一半,直到找到該元素或折半地區的首元素位置高於尾元素位置為止。

程式如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

int search(int *,int,int);

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x;

       printf("請輸入10個數字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("\n");

       printf("請輸入要尋找的數:\n");

       scanf("%d",&x);

       n=search(a,10,x);

       if(n<=0)

       {

              printf("沒有找到你想找得數!");

       }

       else

       {

              printf("你想找的數 %d 在數列的第 %d 個位置。",x,n);

       }

       return0;

}

int search(int *a,int num,int value)

{

       intlow,mid,high;

       low=0;high=num-1;

       while(low<=high)

       {

              mid=(low+high)/2;

              if(a[mid]==value)

              returnmid+1;

              elseif(a[mid]>value)

              high=mid-1;

              else

              low=mid+1;

       }

       return-1;

}

3.      分塊尋找

分塊尋找又稱為索引順序尋找,是介於順序尋找和二分尋找之間的一種尋找方法,它是順序尋找的一種方法。

程式設計如下:

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

#pragma argsused

typedef struct{

int key;

int start;

int end;

}Index;

 

int search(int *,int);

Index index[2];

int _tmain(int argc, _TCHAR* argv[])

{

       inti,a[10],n,x,j=-1;

       printf("請輸入10個數字:\n");

       for(i=0;i<10;i++)

       {

              scanf("%d",a+i);

       }

       printf("請輸入要尋找的數:\n");

       scanf("%d",&x);

       for(i=0;i<2;i++)

       {

              index[i].start=j+1;

              j=j+1;

              index[i].end=j+4;

              j=j+4;

              index[i].key=j;

       }

       n=search(a,x);

       if(n<=0)

       {

              printf("沒有找到你想找得數!");

       }

       else

       {

              printf("你想找的數 %d 在數列的第 %d 個位置。",x,n);

       }

       return0;

}

int search(int *a,int value)

{

       inti,j;

       i=0;

       while((i<2)&&(value>a[index[i].key]))

       i++;

       if(i>=2)

       return-1;

       j=index[i].start;

       while(j<=index[i].end&&a[j]!=value)

       j++;

       if(j>index[i].end)

       j=-1;

       returnj;

}

需要注意的是:分塊尋找中塊的大小可根據表的特徵進行分塊不一定要將線性表分為大小相等的若干塊,各塊可放在不同的向量中,也可將每一塊存放在一個

分塊尋找的優點:

(1)      在表中插入或刪除一個記錄中,只要找到該記錄所屬的塊,就在該塊內進行插入或刪除運算。

(2)      因塊內記錄的存放是任意的,所以插入和刪除比較容易,無需移動大量的記錄。

而這種方法的主要代價就是增加了一個輔助數組的記憶體空間。

4.      雜湊尋找

雜湊尋找是通過電腦資料元素的儲存地址進行尋找的一種方法。其操作步驟為:

(1)      用給定的雜湊函數構造雜湊表

(2)      根據選擇的衝突處理方法解決地址衝突

(3)      在雜湊表的基礎上執行雜湊尋找

建立雜湊表的步驟:

(1)      取資料元素的關鍵字key,計算其雜湊函數值(地址)。若該地址對應的儲存空間還沒有被佔用,則將該元素存入,否則執行(2)解決衝突。

(2)      根據選擇的衝突處理方法,計算關鍵字key的下一個儲存地址,若下一個地址仍被佔用,則繼續執行步驟(2),直到找到能用的儲存地址為止。

設雜湊表為[0~m-1],雜湊函數取H(key),解決衝突的方法是R(x),則雜湊尋找的步驟如下:

(1)      給定K值,計算雜湊地址Di=H(k);若HST為空白,則尋找失敗,若HST=k,則尋找成功。否則執行步驟(2)。

(2)      重複計算處理衝突的下一個儲存地址Dk=R(Dk-1),直到HST[Dk]為空白,或HST[Dk]=k為止。若HST[Dk]=k,則尋找成功,否則尋找失敗。

在應用雜湊尋找時,用先設定一個雜湊函數和一個衝突處理的方法。

雜湊函數的構造有以下幾種方法:

(1)      直接定址法

取關鍵字或者關鍵字的某個線性函數值為雜湊地址。即:

H(key)=key或H(key)=a*key+b;其中,a,b為常數,這種雜湊函數叫做自身函數。

(2)      數字分析法

假設關鍵字是以r為基的數,並且雜湊表中可能出現的關鍵字都是事Crowdsourced Security Testing道的,則可取關鍵字的若干數位組成雜湊地址。

(3)      平方取中法

取關鍵字平方後的中間幾位為雜湊地址。這是一種較常用的構造雜湊函數的方法。通常在選定雜湊函數時不一定能知道關鍵字的全部情況。取其中哪幾位也不合適,而一個數平方後的中間幾位元和數的每一位都相關,由此使隨機分布的關鍵字得到雜湊地址也是隨機的,取得位元由表長決定。

(4)      摺疊法

將關鍵字分割成位元相同的幾部分(最後一部分的位元可以不同),然後取這幾部分的疊加和(含去進位)作為雜湊地址,這種方法稱為摺疊法。關鍵字位元很多,而且關鍵字中每一位上數字分布大致均勻時,可以採用摺疊法得到雜湊地址。

(5)      除留餘數法

取關鍵字被某個不大於雜湊表表長m的數p除後所得餘數為雜湊地址。即:

H(key)=key MOD p, p<=m

這是一種最簡單,最常用的構造雜湊函數的方法,它不僅可以對關鍵字直接模數也可以在摺疊,平方取中等運算之後模數。

(6)      隨機數法

選擇一個隨機函數,取關鍵字的隨機函數值為雜湊地址,即H(key)=random(key)。其中,random為隨機函數,通常,當關鍵字長度不等時採用此法構造呼吸函數較恰當。

處理衝突的方法:

(1)      開放定址法

Hi=(H(key)+di) MOD m i=1,2,3,…,k(k<=m-1)

其中,H(key)為雜湊函數,m為雜湊表表長,di為增量序列

(2)      再雜湊法

RHi均是不同的雜湊函數,即在同義字產生地址衝突時計算另一個雜湊函數地址,直到衝突不再發生。這種方法不易產生“聚集”,但增加了計算的時間。

(3)      鏈地址法

將所有關鍵字為同義字的記錄儲存在同一線性鏈表中,假設雜湊函數所產生的地址在[0,m-1]上,則設立一個指標型向量。Chain ChainHash[m];其每個分量的初始狀態都是null 指標。凡雜湊地址為i的記錄都插入到頭指標為ChainHash[i]的鏈表中。在鏈表的插入位置可以在表頭或表尾,也可以在中間,以保持同義字在同一線性表中按關鍵字有序。

(4)      建立一個公用溢出區

這是處理衝突的一種方法,假設雜湊函數的範圍[0,m-1],則設向量HashTable[0..m-1]為基本表,每個分量存放一個記錄,另設立向量OverTable[0..v]為溢出表。所有關鍵字和基本表中關鍵字為同義字的記錄,不管它們由雜湊函數得到的雜湊地址是什麼,一旦發生衝突,都填入溢出表。

 

程式設計如下:

#include <stdio.h>

#include <alloc.h>

#pragma hdrstop

#include <tchar.h>

//---------------------------------------------------------------------------

 

#pragma argsused

#define MAX 5

//定義結點元素

typedef struct

{

       intnum;

       charname[20];

}ElemType;

//定義雜湊表

typedef struct

{

       ElemType*elem;

       intcount;

       intsizeindex;

}HashTable;

//定義雜湊函數

int Hash(int num)

{

       return(num%5);

}

//建立雜湊表

void InitHash(HashTable *H)

{

       inti;

       H->elem=(ElemType*)malloc(MAX*sizeof(ElemType));

       H->count=0;

       H->sizeindex=MAX;

       for(i=0;i<MAX;i++)

       {

              H->elem[i].num=0;

       }

}

//尋找函數

int SearchHash(HashTable H,int key, int *p)

{

        int c=0;

        *p=Hash(key);

        while(H.elem[*p].num!=key&&H.elem[*p].num!=0)

        {

              c=c+1;

              if(c%2==1)

              {

                     *p=*p+(c+1)*(c+4)/4;

              }

              else

              {

                     *p=*p-(c*c)/4;

              }

        }

        if(H.elem[*p].num==key)

        {

              return1;

        }

        else

        {

          return 0;

        }

}

//插入函數

void InsertHash(HashTable *H,ElemType e)

{

       intp;

       SearchHash(*H,e.num,&p);

       H->elem[p]=e;

   ++H->count;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

       HashTableH;

       intp,key,i;

       ElemTypee;

       InitHash(&H);

       for(i=0;i<MAX;i++)

       {

loop: printf("輸入第 %d 個學生學號\n",i+1);

              scanf("%d",&e.num);

              if(!SearchHash(H,e.num,&p))

              {

                     printf("輸入第 %d 個學生姓名\n",i+1);

                     scanf("%s",e.name);

                     InsertHash(&H,e);

              }

              else

              {

                     printf("該學號已經存在\n");

                     gotoloop;

              }

       }

       printf("請輸入您要尋找的學生學號;\n");

       scanf("%d",&key);

       if(SearchHash(H,key,&p))

       {

              printf("尋找成功,學生的姓名是%s\n",H.elem[p].name);

              printf("該學生所在的位置是 %d\n",p);

       }

       else

       {

           printf("尋找失敗!您要找的學生不存在。");

       }

       return0;

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.