程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> 哈希表實驗C語言版實現

哈希表實驗C語言版實現

編輯:更多關於編程
    以下是對哈希表實驗用C語言實現的代碼進行了詳細的分析介紹,需要的朋友可以參考下   復制代碼 代碼如下:


    /*
     數據結構C語言版 哈希表

    */
    #include <stdio.h>
    #include <malloc.h>
    #define NULLKEY 0 // 0為無記錄標志
    #define N 10  // 數據元素個數
    typedef int KeyType;// 設關鍵字域為整型
    typedef struct
    {
     KeyType key;
     int ord;
    }ElemType; // 數據元素類型
    // 開放定址哈希表的存儲結構
    int hashsize[]={11,19,29,37}; // 哈希表容量遞增表,一個合適的素數序列
    int m=0; // 哈希表表長,全局變量
    typedef struct
    {
     ElemType *elem; // 數據元素存儲基址,動態分配數組
     int count; // 當前數據元素個數
     int sizeindex; // hashsize[sizeindex]為當前容量
    }HashTable;
    #define SUCCESS 1
    #define UNSUCCESS 0
    #define DUPLICATE -1
    // 構造一個空的哈希表
    int InitHashTable(HashTable *H)

     int i;
     (*H).count=0; // 當前元素個數為0
     (*H).sizeindex=0; // 初始存儲容量為hashsize[0]
     m=hashsize[0];
     (*H).elem=(ElemType*)malloc(m*sizeof(ElemType));
     if(!(*H).elem)
      exit(0); // 存儲分配失敗
     for(i=0;i<m;i++)
      (*H).elem[i].key=NULLKEY; // 未填記錄的標志

     return 1;
    }
    //  銷毀哈希表H
    void DestroyHashTable(HashTable *H)
    {
     free((*H).elem);
     (*H).elem=NULL;
     (*H).count=0;
     (*H).sizeindex=0;
    }
    // 一個簡單的哈希函數(m為表長,全局變量)
    unsigned Hash(KeyType K)
    {
     return K%m;
    }
    // 開放定址法處理沖突
    void collision(int *p,int d) // 線性探測再散列

     *p=(*p+d)%m;
    }
    // 算法9.17
    // 在開放定址哈希表H中查找關鍵碼為K的元素,若查找成功,以p指示待查數據
    // 元素在表中位置,並返回SUCCESS;否則,以p指示插入位置,並返回UNSUCCESS
    // c用以計沖突次數,其初值置零,供建表插入時參考。
    int SearchHash(HashTable H,KeyType K,int *p,int *c)
    {
     *p=Hash(K); // 求得哈希地址
     while(H.elem[*p].key!=NULLKEY&&!(K == H.elem[*p].key))
     {
      // 該位置中填有記錄.並且關鍵字不相等
      (*c)++;
      if(*c<m)
       collision(p,*c); // 求得下一探查地址p
      else
       break;
     }
     if (K == H.elem[*p].key)
      return SUCCESS; // 查找成功,p返回待查數據元素位置
     else
      return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置
    }
    int InsertHash(HashTable *,ElemType); // 對函數的聲明
    // 重建哈希表
    void RecreateHashTable(HashTable *H) // 重建哈希表
    {
     int i,count=(*H).count;
     ElemType *p,*elem=(ElemType*)malloc(count*sizeof(ElemType));
     p=elem;
     printf("重建哈希表n");
     for(i=0;i<m;i++) // 保存原有的數據到elem中
      if(((*H).elem+i)->key!=NULLKEY) // 該單元有數據
       *p++=*((*H).elem+i);
     (*H).count=0;
     (*H).sizeindex++; // 增大存儲容量
     m=hashsize[(*H).sizeindex];
     p=(ElemType*)realloc((*H).elem,m*sizeof(ElemType));
     if(!p)
      exit(0); // 存儲分配失敗
     (*H).elem=p;
     for(i=0;i<m;i++)
      (*H).elem[i].key=NULLKEY; // 未填記錄的標志(初始化)
     for(p=elem;p<elem+count;p++) // 將原有的數據按照新的表長插入到重建的哈希表中
      InsertHash(H,*p);
    }
    // 算法9.18
    // 查找不成功時插入數據元素e到開放定址哈希表H中,並返回1;
    // 若沖突次數過大,則重建哈希表。
    int InsertHash(HashTable *H,ElemType e)
    {
     int c,p;
     c=0;
     if(SearchHash(*H,e.key,&p,&c)) // 表中已有與e有相同關鍵字的元素
      return DUPLICATE;
     else if(c<hashsize[(*H).sizeindex]/2) // 沖突次數c未達到上限,(c的閥值可調)
     {
      // 插入e
      (*H).elem[p]=e;
      ++(*H).count;
      return 1;
     }
     else
      RecreateHashTable(H); // 重建哈希表

     return 0;
    }
    // 按哈希地址的順序遍歷哈希表
    void TraverseHash(HashTable H,void(*Vi)(int,ElemType))

     int i;
     printf("哈希地址0~%dn",m-1);
     for(i=0;i<m;i++)
      if(H.elem[i].key!=NULLKEY) // 有數據
       Vi(i,H.elem[i]);
    }
    // 在開放定址哈希表H中查找關鍵碼為K的元素,若查找成功,以p指示待查數據
    // 元素在表中位置,並返回SUCCESS;否則,返回UNSUCCESS
    int Find(HashTable H,KeyType K,int *p)
    {
     int c=0;
     *p=Hash(K); // 求得哈希地址
     while(H.elem[*p].key!=NULLKEY&&!(K == H.elem[*p].key))
     { // 該位置中填有記錄.並且關鍵字不相等
      c++;
      if(c<m)
       collision(p,c); // 求得下一探查地址p
      else
       return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)
     }
     if (K == H.elem[*p].key)
      return SUCCESS; // 查找成功,p返回待查數據元素位置
     else
      return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)
    }
    void print(int p,ElemType r)
    {
     printf("address=%d (%d,%d)n",p,r.key,r.ord);
    }
    int main()
    {
     ElemType r[N] = {
      {17,1},{60,2},{29,3},{38,4},{1,5},
      {2,6},{3,7},{4,8},{60,9},{13,10}
     };
     HashTable h;
     int i, j, p;
     KeyType k;

     InitHashTable(&h);
     for(i=0;i<N-1;i++)
     {
      // 插入前N-1個記錄
      j=InsertHash(&h,r[i]);
      if(j==DUPLICATE)
       printf("表中已有關鍵字為%d的記錄,無法再插入記錄(%d,%d)n",
        r[i].key,r[i].key,r[i].ord);
     }
     printf("按哈希地址的順序遍歷哈希表:n");
     TraverseHash(h,print);
     printf("請輸入待查找記錄的關鍵字: ");
     scanf("%d",&k);
     j=Find(h,k,&p);
     if(j==SUCCESS)
      print(p,h.elem[p]);
     else
      printf("沒找到n");
     j=InsertHash(&h,r[i]); // 插入第N個記錄
     if(j==0) // 重建哈希表
      j=InsertHash(&h,r[i]); // 重建哈希表後重新插入第N個記錄
     printf("按哈希地址的順序遍歷重建後的哈希表:n");
     TraverseHash(h,print);
     printf("請輸入待查找記錄的關鍵字: ");
     scanf("%d",&k);
     j=Find(h,k,&p);
     if(j==SUCCESS)
      print(p,h.elem[p]);
     else
      printf("沒找到n");
     DestroyHashTable(&h);

     system("pause");
     return 0;
    }
    /*
    輸出效果:
    表中已有關鍵字為60的記錄,無法再插入記錄(60,9)
    按哈希地址的順序遍歷哈希表:
    哈希地址0~10
    address=1 (1,5)
    address=2 (2,6)
    address=3 (3,7)
    address=4 (4,8)
    address=5 (60,2)
    address=6 (17,1)
    address=7 (29,3)
    address=8 (38,4)
    請輸入待查找記錄的關鍵字: 17
    address=6 (17,1)
    重建哈希表
    按哈希地址的順序遍歷重建後的哈希表:
    哈希地址0~18
    address=0 (38,4)
    address=1 (1,5)
    address=2 (2,6)
    address=3 (3,7)
    address=4 (4,8)
    address=6 (60,2)
    address=10 (29,3)
    address=13 (13,10)
    address=17 (17,1)
    請輸入待查找記錄的關鍵字: 13
    address=13 (13,10)
    請按任意鍵繼續. . .
    */

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved