Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1184553
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: C/C++

2015-12-02 15:05:42


点击(此处)折叠或打开

  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. #define MAX 16

  5. #define SZ_SIZE 128

  6. typedef char STRING[SZ_SIZE];

  7. /*哈希结点*/
  8. typedef struct hashnode
  9. {
  10.     int key; //初始化为0:表示没有数据
  11.     STRING value; //结点的数据域
  12.     int flag; //有无数据的标志
  13.     int len; //单链表的长度
  14.     struct hashnode * next;
  15. }HashNode;

  16. typedef HashNode * HashNodePtr;

  17. typedef HashNode HASHTABLE[MAX];

  18. void InitHashTable(HASHTABLE list);
  19. int CreateHashTable(HASHTABLE list, int data[], int len);
  20. int Hash(int key);
  21. int CreateHashTable(HASHTABLE list, int data[], int len);
  22. void PrintHashTable(HASHTABLE list);

  23. void AdjustHashTable(HASHTABLE list);
  24. int SortHashNode(HashNodePtr hashheadptr);
  25. int GetHashNode(HashNodePtr hashheadptr, int num, HashNodePtr * hashnodeptr);

  26. int SearchHashTable(HASHTABLE list, int key, HashNodePtr * hashnodeptr);
  27. int InsertHashTable(HASHTABLE list, int key, STRING value);
  28. int DeleteHashTable(HASHTABLE list, int key);

  29. int main(int argc, char * * argv)
  30. {
  31.     printf("链地址哈希表的存储结构!\n");
  32.     HASHTABLE list;
  33.     
  34.     /*关键字序列如下:*/
  35.     int data[12]={19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79};
  36.     
  37.     CreateHashTable(list, data, 12); /*创建哈希表*/
  38.     
  39.     PrintHashTable(list); /*打印哈希表*/
  40.     
  41.     int key;
  42.     HashNodePtr hashnodeptr = NULL;
  43.     
  44.     key = 23;
  45.     SearchHashTable(list, key, &hashnodeptr);
  46.     if(hashnodeptr != NULL)
  47.         printf("key=[%d], value=[%s]\n", key, hashnodeptr->value);
  48.     else
  49.         printf("key=[%d]的元素不存在!", key);
  50.     
  51.     key = 78;
  52.     SearchHashTable(list, key, &hashnodeptr);
  53.     if(hashnodeptr != NULL)
  54.         printf("key=[%d], value=[%s]\n", key, hashnodeptr->value);
  55.     else
  56.         printf("key=[%d]的元素不存在!\n", key);
  57.     
  58.     InsertHashTable(list, key, "key=78");
  59.     key = 92;
  60.     InsertHashTable(list, key, "key=92");
  61.     AdjustHashTable(list); /*调整哈希表*/
  62.     PrintHashTable(list); /*打印哈希表*/
  63.     
  64.     SearchHashTable(list, key, &hashnodeptr);
  65.     if(hashnodeptr != NULL)
  66.         printf("key=[%d], value=[%s]\n", key, hashnodeptr->value);
  67.     else
  68.         printf("key=[%d]的元素不存在!\n", key);
  69.     
  70.     key = 27;
  71.     DeleteHashTable(list, key);
  72.     AdjustHashTable(list); /*调整哈希表*/
  73.     PrintHashTable(list); /*打印哈希表*/
  74.     
  75.     return 0;
  76. }

  77. /**************************************************************
  78.  *函数名:
  79.  *函数功能:
  80.  *
  81. ***************************************************************/

  82. /**************************************************************
  83.  *函数名:DeleteHashTable()
  84.  *函数功能:哈希表中删除一个元素
  85.  *输入参数:
  86.  * list : 哈希表
  87.  * key : 待删除元素的关键字
  88.  *返回值:
  89. ***************************************************************/
  90. int DeleteHashTable(HASHTABLE list, int key)
  91. {
  92.     int flag = -1;
  93.     
  94.     /*元素存在:才需要删除*/
  95.     int index = -1;
  96.     index = Hash(key);
  97.     HashNodePtr p = NULL;
  98.     HashNodePtr t = NULL;
  99.     
  100.     p = &(list[index]); //相当于是表头结点:为空
  101.     while(p->next != NULL)
  102.     {
  103.         if(p->next->key == key) /*找到要删除的结点*/
  104.         {
  105.             t = p->next;
  106.             p->next = t->next; /*删除结点*/
  107.             free(t);
  108.             t = NULL;
  109.             list[index].len--; //链表长度减1
  110.             flag = 1; //待删除的结点存在
  111.             printf("成功删除一个结点:key=[%d]\n", key);
  112.             return 0;
  113.         }
  114.         p = p->next;
  115.     }
  116.     if(flag != 1) //待删除的结点不存在
  117.         printf("key=[%d]结点不存在,不需要删除!\n",key);
  118.         
  119.     return 0;
  120. }

  121. /**************************************************************
  122.  *函数名:InsertHashTable()
  123.  *函数功能:哈希表中新插入一个元素
  124.  *输入参数:
  125.  * list : 哈希表
  126.  * key : 新结点元素关键字
  127.  * value : 新结点数据域
  128.  *返回值:
  129.  *注意:
  130.  * 其实也可以由这个插入算法来实现哈希表的创建
  131. ***************************************************************/
  132. int InsertHashTable(HASHTABLE list, int key, STRING value)
  133. {
  134.     int ret = -1;
  135.     HashNodePtr hashnodeptr = NULL;
  136.     ret = SearchHashTable(list, key, &hashnodeptr);
  137.     if(ret == 0)
  138.     {
  139.         printf("key=[%d]的元素存在,不必要插入!\n", key);
  140.         return -1;
  141.     }
  142.     
  143.     /*元素存在:才需要插入*/
  144.     int index = -1;
  145.     index = Hash(key);
  146.     
  147.     HashNodePtr p = NULL;
  148.     p = (HashNode*)malloc(sizeof(HashNode));
  149.     p->key = key;
  150.     strcpy(p->value, value);
  151.     p->next = list[index].next; /*插在单链表表头后的第1个位置*/
  152.     list[index].next = p;
  153.     
  154.     list[index].flag = 1;
  155.     list[index].len++; /*单链表长度+1*/
  156.     
  157.     return 0;
  158. }

  159. /**************************************************************
  160.  *函数名:SearchHashTable()
  161.  *函数功能:哈希表的查找(根据给定的关键字查找元素)
  162.  *输入参数:
  163.  * list : 哈希表
  164.  * key : 关键字
  165.  *输出参数:
  166.  * hashnodeptr : 查找到的哈希结点指针
  167.  *返回值:
  168.  * 0 : 查找成功, -1 : 查找失败
  169. ***************************************************************/
  170. int SearchHashTable(HASHTABLE list, int key, HashNodePtr * hashnodeptr)
  171. {
  172.     int index = -1;
  173.     index = Hash(key);
  174.     //则结点一定在哈希表的第[index]个位置:但是还不知道是单链表中哪个?
  175.     HashNodePtr p = NULL;
  176.     p = list[index].next;
  177.     while(p != NULL)
  178.     {
  179.         if(p->key == key)
  180.         {
  181.             *hashnodeptr = p;
  182.             return 0;
  183.         }
  184.         p = p->next;
  185.     }
  186.     *hashnodeptr = NULL;
  187.     return -1;
  188. }

  189. /**************************************************************
  190.  *函数名:AdjustHashTable()
  191.  *函数功能:调整哈希表:让单链表中的所有元素递增有序
  192.  *函数参数:
  193.  * list :哈希表
  194. ***************************************************************/
  195. void AdjustHashTable(HASHTABLE list)
  196. {
  197.     int i = -1;
  198.     for(i=0; i<MAX; i++)
  199.     {
  200.         if(list[i].flag == 1) /*有元素才需要调整*/
  201.         {
  202.             SortHashNode(&(list[i])); /*数组中的元素是单链表表头,均为空*/
  203.         }
  204.     }
  205. }

  206. /***************************************************************
  207.  *函数名:SortHashNode()
  208.  *函数功能:按照数据域中某个数据成员的值(key)对单链表的元素进行递增排序
  209.  *函数参数:
  210.  * hashheadptr : 单链表表头指针
  211.  ***************************************************************/
  212. int SortHashNode(HashNodePtr hashheadptr)
  213. {
  214.     int i, j, len;
  215.     HashNodePtr P0 = NULL;
  216.     HashNodePtr P1 = NULL;
  217.     HashNodePtr P2 = NULL;
  218.     
  219.     //printf("对单链表排序如下:\n");
  220.     len = hashheadptr->len;
  221.     /*只能用冒泡法排序:相邻两数比较,对链表来说,交换相邻两数要相对容易的多*/
  222.     for(i=0; i<len-1; i++)
  223.     {
  224.         for(j=0; j<len-1-i; j++)
  225.         {
  226.             GetHashNode(hashheadptr, j, &P0); /*j=0,则P0是头指针*/
  227.             P1 = P0->next;
  228.             P2 = P0->next->next;
  229.             /*P1,P2是要交换的2个节点的指针,P0是这2个节点之前的节点指针*/
  230.             /*3个节点的指针都已经保存,所以就不需要另外定义临时节点指针了*/
  231.             if(P1->key > P2->key)
  232.             {
  233.                 P1->next = P2->next;
  234.                 P2->next = P1;
  235.                 P0->next = P2;
  236.             }
  237.         }
  238.     }
  239.     return 0;
  240. }

  241. /*功能:求单链表中的第num个元素的节点指针*/
  242. int GetHashNode(HashNodePtr hashheadptr, int num, HashNodePtr * hashnodeptr)
  243. {
  244.     HashNodePtr p = NULL;
  245.     int count = 1;
  246.     if(num < 0)
  247.     {
  248.         printf("num值不可小于0!\n");
  249.         return -1;
  250.     }
  251.     if(num == 0)
  252.     {
  253.         *hashnodeptr = hashheadptr;
  254.         return 0;
  255.     }
  256.     p = hashheadptr->next;
  257.     while((p != NULL)&&(count < num))
  258.     {
  259.         p = p->next;
  260.         count++;
  261.     }
  262.     if((p == NULL)||(count < num)) /*第num个元素不存在*/
  263.     {
  264.         printf("count = [%d]\n", count);
  265.         printf("第[%d]个元素不存在!\n", num);
  266.         return -1;
  267.     }
  268.     else if((p != NULL)&&(count == num)) /*第num个元素存在*/
  269.         {
  270.             *hashnodeptr = p;
  271.             return 0;
  272.         }
  273. }

  274. void PrintHashTable(HASHTABLE list)
  275. {
  276.     int i = -1;
  277.     HashNode * p = NULL;
  278.     for(i=0; i<MAX; i++)
  279.     {
  280.         if(list[i].flag == 0)
  281.             printf("第[%d]个记录为空!\n", i);
  282.         else
  283.         {
  284.             printf("第[%d]个记录有[%d]个元素:", i, list[i].len);
  285.             fflush(stdout);
  286.             p = list[i].next;
  287.             while(p != NULL)
  288.             {
  289.                 printf("->[%d]", p->key);
  290.                 p = p->next;
  291.             }
  292.             printf("\n");
  293.         }
  294.     }
  295. }

  296. void InitHashTable(HASHTABLE list)
  297. {
  298.     int i = -1;
  299.     for(i=0; i<MAX; i++)
  300.     {
  301.         list[i].flag = 0; //初始化为0:表示没有数据
  302.         memset(list[i].value, 0, sizeof(STRING));
  303.         list[i].len = 0; //单链表的长度
  304.         list[i].next = NULL; //
  305.     }
  306. }

  307. /*******************************************************************
  308.  *函数名:CreateHashTable()
  309.  *函数功能:创建哈希表
  310.  *输入参数:
  311.  * data[] : 关键字序列存储数组
  312.  * len : 数组长度
  313.  *输出参数:
  314.  * list : 哈希表(是个数组:其中每个元素都是单链表的表头结点)
  315.  *返回值:
  316.  * 0 : 成功, -1 : 失败
  317.  *编程思想:
  318.  * 关键字序列如下:int data[12]={19, 14, 23, 1, 68, 20, 84, 27, 55, 11, 10, 79};
  319.  * 选定的哈希函数:H(key) = key mod 13。
  320.  * 具体:
  321.  * 1,创建一个数组,数组的每个元素是哈希结点元素(可以做空表头,也可以实际存储一个结点元素)
  322.  * 数组的长度是所有可能的哈希函数值的最大值。
  323.  * 2,哈希函数:关键字key,与其对应存储地址之间的函数关系,哈希函数运算得到的即是哈希地址。
  324.  * 3,如果关键字key不同,哈希地址相同:则将后来的元素以单链表的形式链接上去。
  325.  * 4,这样:相同哈希地址的记录链成一个单链表,有的哈希地址可能一直为空,
  326.  * 则有n个哈希地址的函数,最多有n个单链表。
  327.  * 本例中:单链表表头数组为空:单链表是无序的,最后插入的结点是单链表的一个结点元素。
  328.  *注意:
  329.  * 也可以把单链表调整为有序表的操作放在这里
  330. ********************************************************************/
  331. int CreateHashTable(HASHTABLE list, int data[], int len)
  332. {
  333.     InitHashTable(list); /*初始化哈希表*/
  334.     
  335.     int i = -1;
  336.     int index = -1;
  337.     HashNode * p = NULL;
  338.     for(i=0; i<len; i++)
  339.     {
  340.         index = Hash(data[i]);
  341.         //printf("data=[%d], 哈希函数值=[%d]\n", data[i], index);
  342.         
  343.         p = (HashNode*)malloc(sizeof(HashNode));
  344.         p->key = data[i];
  345.         sprintf(p->value, "%d%d%d", data[i], data[i], data[i]);
  346.         p->next = list[index].next; /*插在单链表表头后的第1个位置*/
  347.         list[index].next = p;
  348.         
  349.         list[index].flag = 1;
  350.         list[index].len++; /*单链表长度+1*/
  351.     }
  352.     AdjustHashTable(list); /*调整哈希表*/
  353.     return 0;
  354. }

  355. /*******************************************************************
  356.  *函数名:Hash()
  357.  *函数功能:哈希函数
  358. ********************************************************************/
  359. int Hash(int key)
  360. {
  361.     int index = key % 13;
  362.     return index;
  363. }

阅读(544) | 评论(0) | 转发(0) |
0

上一篇:查找

下一篇:部分线索二叉树

给主人留下些什么吧!~~