哈希表(开散列)

HashOpen.h

#pragma once 



#include<stddef.h>



size_t HashMaxSize=1000; 



typedef int KeyType; 

typedef int ValType; 



typedef size_t (*HashFunc)(KeyType key); 



typedef struct HashElem

{ 

    KeyType key; 

    ValType value; 

    struct HashElem* next; 

} HashElem; 



// 数组的每一个元素是一个不带头结点的链表 

// 对于空链表, 我们使用 NULL 来表示 

typedef struct HashTable

{ 

    HashElem** data; 

    size_t size; 

    HashFunc hash_func; 

} HashTable; 



void HashInit(HashTable* ht, HashFunc hash_func); 



// 约定哈希表中不能包含 key 相同的值. 

int HashInsert(HashTable* ht, KeyType key, ValType value); 



int HashFind(HashTable* ht, KeyType key, ValType* value); 



void HashRemove(HashTable* ht, KeyType key); 



size_t HashSize(HashTable* ht); 



int HashEmpty(HashTable* ht); 



void HashDestroy(HashTable* ht); 

HashOpen.c

#include<stdio.h>

#include<stdlib.h>

#include"HashOpen.h"

#define TEST_HEADER printf("\n==================%s==================\n",__FUNCTION__)



size_t Hashfunc(KeyType Key)

{

    return Key / 10; 

}



HashElem* CreateNode(KeyType key, ValType value)

{

    HashElem* tmp= (HashElem*)malloc(sizeof(HashElem));

    tmp->key=key;

    tmp->value=value;

    tmp->next=NULL;

    return tmp;

}



void DestroyNode(HashElem** elem)

{

    free(*elem);

    *elem=NULL;

}

void HashInit(HashTable* ht, HashFunc hash_func)

{

    if(ht==NULL)

    {

        return;

    }



    ht->data=(HashElem**)malloc(sizeof(HashElem*) * HashMaxSize);



    size_t i;

   

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

    {

        ht->data[i]=NULL;

    }

    ht->size=0;

    ht->hash_func=hash_func;



}



void HashExpansion(HashTable *ht)

{

   int i;

   size_t tmp= HashMaxSize;

  

   HashMaxSize = HashMaxSize* 2 +1; 



   HashElem** old_data=ht->data;

   

    ht->data=(HashElem**)malloc(sizeof(HashElem*)* HashMaxSize); 

    ht->size=0;

   for(i=0;i< (int)HashMaxSize;i++)

   {

       ht->data[i]=NULL;

   }

   

   for(i=0;i<(int)tmp;i++)

   {

        HashElem* cur=old_data[i];

        if(cur!=NULL)

        {

          while(cur!=NULL)

          {

            HashInsert(ht,cur->key, cur->value);

            cur=cur->next;

          }

        }

        else

        {

           continue;

        }

   }



}





// 约定哈希表中不能包含 key 相同的值. 

int HashInsert(HashTable* ht, KeyType key, ValType value)

{

      if(ht==NULL)

      {

          return -1;

      }

       

      if( (ht->size) >=(10*HashMaxSize))

      {

          HashExpansion(ht);

      }



      size_t ret = ht->hash_func(key);

      

       if(ht->data[ret]!=NULL)

      {

          HashElem* to_insert= ht->data[ret];



          while(to_insert->next!=NULL)

          {

              to_insert=to_insert->next;

          }

          

          to_insert->next=CreateNode(key,value);



      }

      else

      {

          ht->data[ret]=CreateNode(key, value);

      }

          ++ht->size;

      return 0;

}



int HashFind(HashTable* ht, KeyType key, ValType* value)

{

   if(ht==NULL)

   {

       return -1;

   }



   size_t ret=ht->hash_func(key);

   

   if(ht->data[ret]==NULL)

   {

       //没找到

       return 1;

   }

   else

   {

       HashElem* cur = ht->data[ret];

       while(cur!=NULL)

       {

           if(cur->key==key)

           {

              *value=cur->value;

              return 0;

           }

           cur=cur->next;

       }

       return 1;

   }

   





}



void HashRemove(HashTable* ht, KeyType key)

{

    if(ht==NULL)

    {

        return;

    }

    size_t ret = ht->hash_func(key);

    

    if(ht->data[ret]==NULL)

    {

        return;

    }

    else

    {

        if(ht->data[ret]->key==key)

        {

           HashElem* to_delete=ht->data[ret];

           ht->data[ret]=to_delete->next;

           DestroyNode(&to_delete);

           --ht->size;

           return;

        }



        HashElem* pre=ht->data[ret];

        HashElem* cur = pre->next;

        

        

        while(cur!=NULL)

        {

           if(cur->key==key)

           {

              pre->next=cur->next;

              DestroyNode(&cur);

              --ht->size;

              return;

           }

           pre=cur;

           cur=cur->next;



        }

    }



}





size_t HashSize(HashTable* ht)

{

    return ht->size;

}



int HashEmpty(HashTable* ht)

{

    if(ht==NULL)

    {

        return -1;

    }

    if(ht->size==0)

    {

      return 0;

    }

    else

    {

        return 1;

    }





}



void HashDestroy(HashTable* ht)

{

    if(ht==NULL)

    {

        return;

    }

    size_t i;



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

    {



        if(ht->data[i]!=NULL)

        {

        

            HashElem* to_delete=ht->data[i];

            ht->data[i]=NULL;

            

            HashElem* after = to_delete->next;



            while(to_delete!=NULL)

            {

              free(to_delete);

               --ht->size;

              to_delete=after;



              if(after!=NULL)

              {

                after=after->next;

              }



            }

        }

        

    }



}



void ShowLinkedList(HashElem* elem)

{

    while(elem!=NULL)

    { 

        printf("key-value:%5d-%5d\n",elem->key,elem->value);

        elem=elem->next;

    }

}



void ShowHashTable(HashTable* ht, char* str)

{

    printf("\n------------%s------------\n",str);

    printf("            HashTable          \n");

    printf("data: %10p\n",ht->data);

    printf("size: %10lu\n", ht->size);

    printf("func: %10p\n", ht->hash_func);





}

void TestInit()

{

  TEST_HEADER;

  HashTable ht;

  HashInit(&ht,Hashfunc);

  ShowHashTable(&ht, (char*)"init");



}



void TestInsert()

{

  TEST_HEADER;

  HashTable ht;

  HashInit(&ht,Hashfunc);

  

  ShowHashTable(&ht,(char*)"before insert 15000 elemt");

  size_t i;



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

  {

    HashInsert(&ht,i,i*4);

  }

  ShowHashTable(&ht,(char*)"after insert 15000 elemt");

  ShowLinkedList(ht.data[3]);

} 





void TestFind()

{

   

  TEST_HEADER;

  HashTable ht;

  HashInit(&ht,Hashfunc);

  

  size_t i;

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

  {

    HashInsert(&ht,i,i*4);

  }

  ValType  value;

 int ret= HashFind(&ht,10034,&value);

 printf("ret:%d  key-value:%5d-%5d\n",ret, 10034, value);



}



void TestRemove()

{



  TEST_HEADER;

  HashTable ht;

  HashInit(&ht,Hashfunc);

  

  size_t i;

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

  {

    HashInsert(&ht,i,i*4);

  }

 

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

  {

    HashRemove(&ht,i);

  }

   ShowHashTable(&ht, (char*)"After remove");

}



void TestDestroy()

{

  TEST_HEADER;

  HashTable ht;

  HashInit(&ht,Hashfunc);



  size_t i;

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

  {

    HashInsert(&ht,i,i*4);

  }

  HashDestroy(&ht);

   ShowHashTable(&ht, (char*)"After destroy");

}



int main()

{

    TestInit();

    TestInsert();

    TestFind();

    TestRemove();

    TestDestroy();

    return 0;

}

Makefile

HashOpen:HashOpen.c
	gcc -o $@ $^

运行结果:

[abc123@localhost hash_open]$ ./HashOpen 

==================TestInit==================

------------init------------
            HashTable          
data:  0x183c010
size:          0
func:   0x400610

==================TestInsert==================

------------before insert 15000 elemt------------
            HashTable          
data:  0x183df60
size:          0
func:   0x400610

------------after insert 15000 elemt------------
            HashTable          
data:  0x188e0b0
size:      15000
func:   0x400610
key-value:   30-  120
key-value:   31-  124
key-value:   32-  128
key-value:   33-  132
key-value:   34-  136
key-value:   35-  140
key-value:   36-  144
key-value:   37-  148
key-value:   38-  152
key-value:   39-  156

==================TestFind==================
ret:0  key-value:10034-40136

==================TestRemove==================

------------After remove------------
            HashTable          
data:  0x19803d0
size:          0
func:   0x400610

==================TestDestroy==================

------------After destroy------------
            HashTable          
data:  0x1984260
size:          0
func:   0x400610

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值