2013-08-06 35 views
0

我有散列表separetaly鏈表。我成功將我的元素存儲在散列表中,但當我嘗試搜索存儲的元素時失敗。我的函數lookup_string應該在散列表中找到正確的列表,並且如果使用相同的散列鍵存儲多個元素,則通過for循環遍歷鏈表。搜索散列表不工作,爲循環不執行在c

lookup_string函數中,我發現for循環從不執行(我用打印來檢查),函數跳過for循環並直接返回NULL。這種行爲真的很奇怪,我不知道它爲什麼會跳過這個循環,但這就是我存儲它們後無法找到我的元素的原因,至少是我的想法。

如果有人可以解釋這個問題,將不勝感激!

我有刪除哈希表中的元素,但這些都沒有必要考慮,我只是上傳他們的目的。我在菜單中選擇替代項1來添加一個元素,然後在菜單中添加替代項3,那就是當我找不到我存儲的元素時。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct post     // structure of node 
{  
    char name[30];   // stored data 
    int tel;    // stored data 
    struct post *next;  // reference to next node 
}; 

typedef struct post Post; // Post = struct post 

struct list 
{ 
    Post *head;   
    Post *current;    
}; 

typedef struct list List; 

struct hash_table 
{ 
    List *table; 
    int size; 
}; 

typedef struct hash_table Post_table; 

Post* CreateList(char tempname[30], int temptel) 
{ 
    Post *ptr = (Post*)malloc(sizeof(Post)); 

    strcpy(ptr->name, tempname);  
    ptr->tel = temptel; 
    ptr->next = NULL; 

    printf("\n creating list with headnode as [%s]\n",tempname); 

    return ptr; 
} 

Post* AddList(char tempname[30], int temptel, Post *current) 
{ 
    if(current == NULL) 
    { 
     return (CreateList(tempname, temptel)); 
    } 

    printf("\n Adding node to end of list with value [%s]\n",tempname); 
    Post *ptr = (Post*)malloc(sizeof(Post)); 

    strcpy(ptr->name, tempname); 
    ptr->tel = temptel; 
    ptr->next = NULL; 

    current->next = ptr; 

    return ptr; 
} 

unsigned int Hash(Post_table *hash_table, char tempname[30]) 
{ 
    int i, sum, key; 

    for(i = 0; i < strlen(tempname); i++) 
    { 
     sum += (int)tempname[i]; 
    } 

    key = abs(sum % hash_table->size); 
    return key; 
} 

Post_table *create_hash_table(int size) 
{ 
    Post_table *new_table; 

    if (size < 1) 
    {return NULL;} 

    // attempt to allocate memory for the table structure 
    if ((new_table = malloc(sizeof(Post_table))) == NULL) 
    {return NULL;} 

    // attempt to allocate memory for the table itself 
    // calloc() = all head and current are initialized with NULL 
    if ((new_table->table = calloc(size,sizeof(List *) * size)) == NULL) 
    {return NULL;} 

    new_table->size = size; 
    return new_table; 
} 

Post *lookup_string(Post_table *hash_table, char tempname[30]) 
{ 
    Post *list; 
    unsigned int hashkey = Hash(hash_table, tempname); 
    printf("testprint-1"); 

    // Go to the correct list based on the hash value and see if str is 
    // in the list. If it is, return return a pointer to the list element. 
    // If it isn't, the item isn't in the table, so return NULL. 
    for(list = hash_table->table[hashkey].head; list != NULL; list = list->next) 
    { 
     printf("testprint-2"); 
     if (strcmp(tempname, list->name) == 0) 
     { 
      return list; 
     } 
    } 
    return NULL; 
} 

int add_string(Post_table *hash_table, char tempname[30], int temptel) 
{  
    Post *current_list; 

    unsigned int hashkey = Hash(hash_table, tempname); 
    printf("\nHash-key: %d\n", hashkey); 

    // if item already exists, don't insert it again 
    current_list = lookup_string(hash_table, tempname); 
    if (current_list != NULL) 
    { 
     return 2; 
    } 

    hash_table->table[hashkey].current = AddList(tempname, temptel, hash_table->table[hashkey].current); 

    // if the list has been created just now, then both head and current must point to the only list element 
    if(hash_table->table[hashkey].head == NULL) 
    { 
     hash_table->table[hashkey].head = hash_table->table[hashkey].current; 
    } 
    return 0; 
} 

void free_entry(Post_table *hash_table, char tempname[30]) 
{ 
    Post *del_list; 
    Post *temp; 
    int ret = 0; 

    unsigned int hashkey = Hash(hash_table, tempname); 
    del_list = lookup_string(hash_table, tempname); 
    ret = Delete(hash_table, tempname, hashkey); 

    if(ret != 0) 
    { 
     printf("\n delete [name = %s] failed, no such element found\n",tempname); 
    } 
    else 
    { 
     printf("\n delete [name = %s] passed \n",tempname); 
    } 
} 

void skrivMeny(void) 
{ 
    printf("\n1: Register name and telephone number\n"); 
    printf("2: Remove name and telephone number\n"); 
    printf("3: Search for name\n"); 
    printf("5: Exit\n"); 
} 

Post* Search(Post_table *hash_table, unsigned int hashkey, char tempname[30], Post **prev) 
{ 
    Post *ptr = hash_table->table[hashkey].head; 
    Post *tmp = NULL; 
    int found = 0; 
    char structname[sizeof(tempname)]; 

    printf("\n Searching the list for value [%s] \n",tempname); 

    while(ptr != NULL) 
    { 
     if (strcmp(ptr->name, tempname) == 0) 
     { 
      found = 1; 
      break; 
     } 

     else 
     { 
      tmp = ptr; 
      ptr = ptr->next; 
     } 
    } 

    if(found == 1) 
    { 
     if(prev) 
     { 
      *prev = tmp; 
     } 
     return ptr; 
    } 

    else 
    { 
     return NULL; 
    } 
} 

int Delete(Post_table *hash_table, char tempname[30], unsigned int hashkey) 
{ 
    Post *prev = NULL; 
    Post *del = NULL; 

    printf("\n Deleting value [%s] from list\n",tempname); 
    del = Search(hash_table, hashkey, tempname, &prev); 

    if(del == NULL) 
    { 
     return -1; 
    } 

    else 
    { 
     if(prev != NULL) 
     { 
      prev->next = del->next; 
     } 

     if(del == hash_table->table[hashkey].current && del != hash_table->table[hashkey].head) 
     { 
      hash_table->table[hashkey].current = prev; 
     } 

     else if(del == hash_table->table[hashkey].head) 
     { 
      hash_table->table[hashkey].head = del->next; 
     } 
    } 

    free(del); 
    del = NULL; 
    return 0; 
} 


int main() 
{ 
    printf("\nHej och välkommen till hashlistan\n\n"); 
    int menyval = 1; 
    char tempname[30]; 
    int temptel, key; 

    Post * ptr; 

    Post_table *hash_table; 
    int table_size = 10; 
    hash_table = create_hash_table(table_size); 

    while (menyval > 0 && menyval <= 5) 
    { 
     skrivMeny(); 
     scanf("%d", &menyval); 

     if (menyval == 1) 
     { 
      printf("[Name] [Number] = "); 
      scanf("%s %d", &tempname[0], &temptel); 
      add_string(hash_table, tempname, temptel); 
     } 

     if (menyval == 2) 
     {  
      printf("[Name] = "); 
      scanf("%s", &tempname[0]); 
      free_entry(hash_table, tempname); 
     } 

     if (menyval == 3) 
     { 
      printf("[Name] = "); 
      scanf("%s", &tempname[0]); 
      ptr = lookup_string(hash_table, tempname); 

      if(ptr == NULL) 
      { 
       printf("\n Search [name = %s] failed, no such element found\n",tempname); 
      } 
      else 
      { 
       printf("\n Search passed [name = %s tel = %d]\n",ptr->name, ptr->tel); 
      } 
     } 

     if (menyval == 5) 
     { 
      break; 
     } 

    } 
    return 0; 
} 
+0

TL; DR。 <! - 15個字符 - > – 2013-08-06 21:31:18

+2

這個網站是針對特定的問題,而不是尋找bug。請找出您不明白的程序的確切區域,並用可定義的答案詢問具體問題。謝謝 – wespiserA

+1

要調試您的問題,您需要更多信息。問問自己:「我如何驗證我想要插入到散列表中的字符串實際上已插入?」當你能夠回答這個問題,然後真正進行驗證時,你將更接近自己解決這個問題。 – jxh

回答

2

一兩件事,可能是問題是,在你的Hash功能,你聲明sum沒有它初始化爲0。我的猜測是,for循環不「lookup_string」執行,因爲「列表」爲NULL首先,因爲每次你調用它(即使有相同的參數),'哈希'也不一定是相同的。

也許來代替:

int i, sum, key; 

地說:

int i, key, sum = 0; 
+0

非常感謝你puppyofkosh!你是一個非常有幫助的人。直到現在,我還不知道在聲明期間初始化變量的重要性。我一直困惑着爲什麼有時候人們選擇初始化,有時卻不會。 – AznBenny