Chinaunix首页 | 论坛 | 博客
  • 博客访问: 742767
  • 博文数量: 141
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1115
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-17 14:32
个人简介

小公司研发总监,既当司令也当兵!

文章分类

全部博文(141)

分类: LINUX

2016-01-02 22:40:29

hash算法原理本文就不累赘讲述了,百度/google一下就知道了。

本demo程序实现一个简单的联系人hash表,通过姓名查找联系人:
1. hash函数采用简单的姓名字母累加和,通过掩码映射的方式获取hash-key;
2. 冲突解决采用链式散列;
3.由于联系人姓名(拼音)累加和分布相对集中(几百到两千左右),因此该hash表容量一般小于2000冲突较少,如果联系人数量较多,该hash函数冲突会增加。

点击(此处)折叠或打开

  1. /**
  2. * 联系人hash表实现demo
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>

  7. struct HashTableEntry {
  8.     int flag;
  9.     int nextIndex;
  10.     int prveIndex;
  11.     char* name;
  12. };
  13.     
  14. struct PeopleHashTable {
  15.     unsigned int size;
  16.     unsigned int entrys;
  17.     struct HashTableEntry *datas;
  18. };

  19. enum EntryFlag {
  20.     STATE_UNUSED = 0,
  21.     STATE_HASH_USED,
  22.     STATE_COLLISION_USED
  23. };

  24. int getUpperSize(int size)
  25. {
  26.     int upperSize = 1;

  27.     if (size <= 0)
  28.         return 1;

  29.     while (upperSize < size)
  30.         upperSize <<= 1;

  31.     return upperSize;

  32. }

  33. int getHashKey(struct PeopleHashTable *table, const char *name)
  34. {
  35.     char *ptr;
  36.     unsigned key = 0;

  37.     if (NULL == name)
  38.         return -1;

  39.     ptr = name;

  40.     while ('\0' != *ptr)
  41.     {
  42.         key += *ptr;
  43.         ptr++;
  44.     }

  45.     printf("sum of %s: [%d], and key : [%d]\n",name, key, key & (table->size -1));
  46.     if (NULL == table)
  47.         return key;

  48.     return (key & (table->size -1));
  49. }

  50. int insert2Table(struct PeopleHashTable *table, char *name)
  51. {
  52.     int key = 0;
  53.     struct HashTableEntry *entry;
  54.     struct HashTableEntry *tmp;

  55.     int i;

  56.     if (NULL == table)
  57.         return -1;

  58.     if (table->entrys == table->size)
  59.     {
  60.         printf("table is full, can NOT insert only more!\n");
  61.         return -1;
  62.     }

  63.     key = getHashKey(table, name);
  64.     entry = &(table->datas[key]);

  65.     if (entry->flag == STATE_UNUSED)
  66.     {
  67.         entry->flag = STATE_HASH_USED;
  68.         entry->name = name;
  69.         table->entrys++;
  70.         return 0;
  71.     }

  72.     if (entry->flag == STATE_HASH_USED)
  73.     {
  74.         // find a useable entry
  75.         for (i = 0; i < table->size; i++)
  76.         {
  77.             if (table->datas[i].flag == STATE_UNUSED)
  78.                 break;
  79.         }

  80.         // find if entry has a collision entry
  81.         while( entry->nextIndex != -1)
  82.         {
  83.             entry = &table->datas[entry->nextIndex];
  84.         }

  85.         tmp = &(table->datas[i]);

  86.         tmp->flag = STATE_COLLISION_USED;
  87.         tmp->name = name;
  88.         tmp->prveIndex = key;

  89.         entry->nextIndex = i;
  90.         table->entrys++;
  91.         return 0;
  92.     }
  93.     
  94.     if (entry->flag == STATE_COLLISION_USED)
  95.     {
  96.         // find a useable entry
  97.         for (i = 0; i < table->size; i++)
  98.         {
  99.             if (table->datas[i].flag == STATE_UNUSED)
  100.                 break;
  101.         }

  102.         // remove current entry to the empty entry space
  103.         tmp = &table->datas[entry->prveIndex];
  104.         tmp->nextIndex = i;

  105.         tmp = &table->datas[i];
  106.         tmp->prveIndex = entry->prveIndex;
  107.         tmp->flag = entry->flag;
  108.         tmp->name = entry->name;
  109.         tmp->nextIndex = entry->nextIndex;

  110.         entry->flag = STATE_HASH_USED;
  111.         entry->name = name;
  112.         entry->prveIndex = -1;
  113.         entry->nextIndex = -1;

  114.         table->entrys++;
  115.         return 0;
  116.     }

  117.     return -1;
  118. }

  119. struct HashTableEntry* findPeople(struct PeopleHashTable *table, char *name)
  120. {
  121.     int key;
  122.     struct HashTableEntry *entry = NULL;

  123.     if (NULL == table)
  124.         return NULL;

  125.     key = getHashKey(table, name);

  126.     entry = &table->datas[key];
  127.     if (entry->name != NULL && !strcmp(entry->name, name))
  128.     {
  129.         return entry;
  130.     }

  131.     while(entry)
  132.     {
  133.         if (entry->name && !strcmp(entry->name, name))
  134.             return entry;

  135.         if (entry->nextIndex != -1)
  136.             entry = &table->datas[entry->nextIndex];
  137.         else
  138.             return NULL;
  139.     }
  140.     return NULL;
  141. }

  142. int createHashTable(struct PeopleHashTable **table, unsigned int size)
  143. {
  144.     int upperSize = getUpperSize(size);

  145.     struct PeopleHashTable *tablePtr = NULL;
  146.     struct HashTableEntry *entryList = NULL;
  147.     int i;

  148.     tablePtr = (struct PeopleHashTable*)malloc(sizeof(*tablePtr));
  149.     if (NULL == tablePtr)
  150.         return -1;

  151.     entryList = (struct HashTableEntry*)malloc(sizeof(*entryList) * upperSize);
  152.     if (NULL == entryList)
  153.     {
  154.         free(tablePtr);
  155.         return -1;
  156.     }
  157.     memset(entryList, 0, sizeof(*entryList) * upperSize);
  158.     for(i = 0; i < upperSize; i++)
  159.     {
  160.         entryList[i].flag = STATE_UNUSED;
  161.         entryList[i].name = NULL;
  162.         entryList[i].nextIndex = -1;
  163.         entryList[i].prveIndex = -1;
  164.     }

  165.     tablePtr->datas = entryList;
  166.     tablePtr->entrys = 0;
  167.     tablePtr->size = upperSize;

  168.     *table = tablePtr;

  169.     return 0;
  170. }

  171. int destoryHashTable(struct PeopleHashTable *table)
  172. {
  173.     if (NULL == table)
  174.         return 0;

  175.     free(table->datas);
  176.     free(table);

  177.     return 0;
  178. }

  179. static void debug_print_table(struct PeopleHashTable *table)
  180. {
  181.     int i;

  182.     printf("table infos:\n");
  183.     printf("size: [%d], entry numbers;[%d]\n", table->size,table->entrys);
  184.     printf("index flag prve next name\n");
  185.     for (i = 0; i < table->size; i++)
  186.     {
  187.         printf("%5d%5d%5d%5d %s\n", i,table->datas[i].flag ,table->datas[i].prveIndex, table->datas[i].nextIndex, table->datas[i].name == NULL ? "--" :table->datas[i].name);
  188.     }
  189. }
  190. /*
  191. void main()
  192. {
  193.     char *peoples[30]= {
  194.         "刘敏",
  195.         "wang wu",
  196.         "li si",
  197.         "liu yu gu",
  198.         "jiang jie hui",
  199.         "tan wei wei",
  200.         "liu tao",
  201.         "mi yue",
  202.         "mi shu",
  203.         "yin si",
  204.         "yin dang",
  205.         "huang zi",
  206.         "zhang zi",
  207.         "qu yuan",
  208.         "tang jia jun",
  209.         "gui wa zi",
  210.         "qu li zi",
  211.         "gong zhu",
  212.         "tang hui",
  213.         "jiu zhong",
  214.         ""
  215.     };

  216.     struct PeopleHashTable *table;
  217.     struct HashTableEntry *entry;

  218.     int ret;
  219.     int i;

  220.     ret = createHashTable(&table, 20);

  221.     if (ret < 0)
  222.     {
  223.         printf("create hash table fail\n");
  224.         return;
  225.     }

  226.     i = 0;
  227.     for (i = 0; i < 20; i++)
  228.     {
  229.         insert2Table(table,peoples[i]);
  230.     }
  231.     printf("-- add people done!\n");
  232.     
  233.     debug_print_table(table);


  234.     entry = findPeople(table, "jiu zhong");
  235.     if (entry != NULL)
  236.     {
  237.         printf("find!\n");
  238.     }
  239.     else
  240.         printf("--no--\n");

  241.     destoryHashTable(table);
  242.     table = NULL;
  243. }*/



阅读(2271) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~