自己寫的一個雜湊表的實現

來源:互聯網
上載者:User

        雜湊表是數組、鏈表及數學演算法的一個綜合應用, 無論在理論上還是實踐上都是非常有價值的。 廢話不多說了, 貼上自己的實現吧,以供參考,有錯誤之處,懇請指出。 還需要做的一個工作是, 為實現中用到的鏈表和雜湊表設計詳盡苛刻的測試。

        該雜湊表包括四個檔案: common.h , LinkList.c, Hashtable.c , main.c . 將它們放在同一個檔案夾中,按照下面的方式編譯運行

        $ gcc -Wall *.c -o main

        $ main

        或者 一個簡單的 makefile 檔案: 

        OBJS = Hashtable.o main.o LinkList.o
         mhash: $(OBJS)
         [tab]cc -o mhash $(OBJS)
         HashSearch.o: Hashtable.c common.h
         [tab]cc -c Hashtable.c
         main.o: main.c common.h
         [tab]cc -c main.c
         LinkList.o: LinkList.c common.h
         [tab]cc -c LinkList.c  
         .PHONY: clean
         clean:
         [tab]-rm $(OBJS) mhash
        

         $ make

         $ mhash

         下面是各個檔案的具體實現: 

         common.h

   

/* * common.h * 關於雜湊尋找和鏈表結構的聲明和定義。 * * 雜湊尋找法:  * 採用字串散列函數的雜湊函數和鏈地址法的衝突解決方案 * */enum { OK = 1, ERROR = 0, TRUE = 1, FALSE = 0, FAILURE = 1, LEN_OF_TABLE = 13, RECORD_NUM = 95 }; typedef struct {          /* 記錄類型 */         char  *key; int   value; } Record;typedef struct node *LLNptr;typedef struct node {     /*  鏈表結點類型 */     Record  data;     LLNptr  next;  } LLNode;typedef int  Status;/* 單鏈表的函式宣告,主要依照嚴蔚敏老師《資料結構C語言版》中的描述 */ Status  InitList(LLNptr *list);              /* 建立帶頭結點的單鏈表 */    int     IsEmpty(LLNptr list);                /* 判斷單鏈表是否為空白   */int     ListLength(LLNptr list);             /* 返回鏈表長度,即記錄的數目(不含頭結點) */Status  GetRecord(LLNptr list, int i, Record *e);      /* 返回鏈表中第 i 個位置上的結點,並儲存在 e 中 */Status  ListInsert(LLNptr list, int i, Record e);      /* 將記錄 e 插入到鏈表 list 中的第 i 個位置上 */Status  ListDelete(LLNptr list, int i, Record *e);     /* 將鏈表 list 中的第 i 個位置上的記錄刪除,並用 e 返回 */Status  ListTraverse(LLNptr list, void (*visit)(Record *e));  /* 使用 visit 遍曆鏈表 */Status  ListPrint(LLNptr list);                        /* 列印鏈表內容 */      void  printRecord(Record *e);                          /* 列印記錄內容 */int   Equal(Record *e1, Record *e2);                   /* 判斷記錄的相等性 *//* 返回鏈表 list 中與 e 滿足 compare 關係的記錄的指標; 如果不存在,返回 NULL */Record*  PLocateRecord(LLNptr list, Record e, int (*compare)(Record *e1, Record *e2));/* 雜湊尋找的函式宣告  */int hash(char* key);     /* 計算關鍵字的雜湊值 */Status InitTable(LLNptr hashtable[]);    /* 初始化雜湊表 hashtable */Status HashInsert(LLNptr hashtable[], Record e);   /* 將記錄插入雜湊表 hashtable 中 */Record* HashSearch(LLNptr hashtable[], Record e);      /* 根據記錄關鍵字尋找:若有則返回指向該記錄的指標,否則返回 NULL */Status HashTraverse(LLNptr hashtable[]);           /* 遍曆雜湊表 */

      LinkList.c

      

/*  LinkList.c  *//*  帶頭結點的單鏈表實現,頭結點儲存表長資訊  */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"Status  InitList(LLNptr* list){  LLNptr head = (LLNptr)malloc(sizeof(LLNode)); if (!head) {           fprintf(stderr, "Error: fail to allocate memory!\n");            return ERROR;         }          head->data.value = 0;      /* 頭結點的 value 域儲存表長 */           head->data.key = NULL;     /* 頭結點的 key 域 未用     */   head->next = NULL;         *list = head; return  OK;}  int  IsEmpty(LLNptr list){return list->data.value == 0;}int  ListLength(LLNptr list){return list->data.value;}Status GetRecord(LLNptr list, int i, Record *e){  /* 取得表list中的第i個元素, 並用e返回 */    LLNptr p = list->next;   /* p 指向第一個記錄結點 */            if (IsEmpty(list)) {   fprintf(stderr, "Error: list empty!\n");   return  ERROR;  }  if (i < 1 || i > ListLength(list)) {   fprintf(stderr, "Error: position parameter %d out of range!\n", i);   return  ERROR;  }  while(--i) p = p->next;  /* p 指向第i個元素 */  *e = p->data;  return OK;   }Record* PLocateRecord(LLNptr list, Record e, int (*compare)(Record *e1, Record *e2)){    /* 返回表list中與給定元素e滿足compare關係的記錄指標 */    LLNptr p = list->next;     while (p) {     if (compare(&p->data, &e))    return &p->data;     p = p->next;  }  return NULL;  }Status  ListInsert(LLNptr list, int i, Record e){  /* 將記錄 e 插入表list中的第 i 個位置上 */  LLNptr s, p = list;  int j = 0;    /* j 作計數器 */            if (i < 1 || i > ListLength(list)+1) {   fprintf(stderr, "Error: position parameter %d out of range!\n", i);   return  ERROR;  }  while (p && j < i-1) { p = p->next; j++; }  s = (LLNptr)malloc(sizeof(LLNode));  if (!s) {    fprintf(stderr, "Error: fail to allocate memory!\n");    return ERROR;  }  s->data = e; s->next = p->next;  p->next = s;  list->data.value++;  return OK;}Status  ListDelete(LLNptr list, int i, Record *e){  /* 刪除表list中的第i個位置上的記錄,並用 e 返回 */    LLNptr p1 = list;  LLNptr p2;  int j = 0;  /* j 作計數器 */    if (IsEmpty(list)) {   printf("Error: list empty!\n");   return  ERROR;  }  if (i < 1 || i > ListLength(list)) {   printf("Error: invalid index!\n");   return  ERROR;  }  while (p1->next && j < i-1) { /* p1 指向第 i-1 個元素 */    p1 = p1->next;    j++;  }  p2 = p1->next;         /* p2 指向第 i 個元素 */          *e = p2->data;          p1->next = p2->next;          free(p2);          list->data.value--;  return OK;  }Status  ListTraverse(LLNptr list, void (*visit)(Record *e)){/* 用visit函數遍曆表list中的元素有且僅有一次 */ LLNptr p = list->next;  if (IsEmpty(list)) {   printf("list empty!\n");   return  ERROR;  } while (p) {  visit(&p->data);  p = p->next; } return OK;}Status ListPrint(LLNptr list){    return ListTraverse(list, printRecord);}void  printRecord(Record *e){ printf("(%s, %d)\n", e->key, e->value);}int   Equal(Record *e1, Record *e2){ return strcmp(e1->key,e2->key)==0;}

     Hashtable.c

     

// Hashtable.c// 雜湊函數的實現#include <stdio.h>#include "common.h" int hash(char* key){ char *p = key;         int hash = 17;         while (*p) {            hash = hash * 37 + (*p);            p++;         }         printf("key = %s\thash = %d , hash %% %d = %d\n" , key, hash, LEN_OF_TABLE, hash % LEN_OF_TABLE); return hash % LEN_OF_TABLE;}Status InitTable(LLNptr table[]){ int i; for (i = 0; i < LEN_OF_TABLE; i++) {    if (!InitList(&table[i])) {                return ERROR;            } } return OK;}Status HashInsert(LLNptr table[], Record e){       int t_index = hash(e.key);         if (PLocateRecord(table[t_index], e, Equal)) {  /* 雜湊表中已存在該記錄 */             printf("Record exists, nothing to do.");             return OK;         } int ins_pos = ListLength(table[t_index]) + 1; if (!ListInsert(table[t_index], ins_pos, e)) {             return ERROR;         }  return OK;}Record* HashSearch(LLNptr table[], Record e){   int t_index = hash(e.key); return PLocateRecord(table[t_index], e, Equal);}Status HashTraverse(LLNptr table[]){int i;        printf("The hash table:\n");for (i = 0; i < LEN_OF_TABLE; i++) {           printf("List[%d]:\n", i);    ListPrint(table[i]);   printf("\n");}return OK; }

       main.c

       

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"char* toString(int i);int main(){         printf("Program start up ...\n");         /* 表長為LEN_OF_TABLE的雜湊表,每個元素為一個單鏈表指標 */         LLNptr hashtable[LEN_OF_TABLE];                  Record rds[RECORD_NUM];         Record* pe;         Record* qe; int i; if (!InitTable(hashtable)) {    fprintf(stderr, "Error: fail to initialize the hashtable!\n");    exit(FAILURE); }         printf("initialize the hashtable successfully!\n");         HashTraverse(hashtable);           for (i = 0; i < RECORD_NUM; i++) {              rds[i].key = toString(i);              rds[i].value = i;              printf("Record: (%s %d) \n", rds[i].key, rds[i].value);              printf("prepare to insert ...");              if (!HashInsert(hashtable, rds[i])) {                 printf("failed to insert record!");              }             } HashTraverse(hashtable);         pe = (Record* ) malloc(sizeof(Record));         pe->key = "11111";         qe = HashSearch(hashtable, *pe);         if (qe != NULL) {            printRecord(qe);         }         else {            printf("Record Not Found.\n");         }                  pe->key = "11112";         qe = HashSearch(hashtable, *pe);         if (qe != NULL) {            printRecord(qe);         }         else {            printf("Record Not Found.\n");         }  return 0;}char* toString(int i){   char *p = (char *)malloc(5*sizeof(char) + 1);   char *q;   if (!p) {      fprintf(stderr, "Error, fail to allocate memory.");      exit(FAILURE);   }   q = p;   while (q < p+5) {       *q = i + ' ';       q++;      }   *q = '\0';   return p;}

     

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.