哈希结构

/*
    哈希结构:数据和地址的一种映射关系
    映射关系:数学中的函数关系
    哈希地址:不是指真正意义上的地址(指针),抽象的参照地址。
    举例:数组数组下标就可以充当哈希地址
       第一种:直接定址法
       int   arrayHash[10];   //哈希的内存
       y=x       //构造函数,数据就是直接的地址
       arrayHash[1]=1;  //数字 1 直接存放到 arrayHash[1] 里面
       arrayHash[2]=2;  // 2 就存放到arrayHash[2]里面

       第二种:用得比较多的哈希构造函数是 取余法
       例:
       y = x%p;
       //假设有一堆数据:1       4         19       11         23    存放到哈希结构里去
            y = x%10;   
            //这样子,它只有九个地址,为0-9   
            //构造函数,能确定他能产生几个地址,1取10的余还是 1
       int   arrayHash[10];
             arrayHash[1%10] = 1;
             arrayHash[2%10] = 2;
             arrayHash[4%10] = 4;
             arrayHash[19%10] = 19;
             //哈希冲突:在哈希地址中已经存在了元素
                       arrayHash[11%10] = 11
             //哈希冲突解决方案: 
                  《1》.开放地址法:
                   11%10本为1,但 1 已存在,所以arrayHash[11%10]将会储存在其他空余的内存当中,开放地址法一般情况上,哈希地址个数是大于元素个数
                  《2》.数组链表的方式:
                  当产生冲突的时候,它会以发生冲突的元素(arrayHash[1%10]与arrayHash[11%10]发生冲突)为表头创建一个链表(数据结构的图也是这种方式)
             有时数据不满足数据结构需求时,需要自己构造函数
          以字符为例,数据是字符串
*/

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

//数组哈希
struct   pair
{
      int    first;              //构造一个关键字,为构建哈希地址做准备
      char   second[];   //数据
};

//哈希表特征
struct     hashTable
{
      /*用二级指针,方便判断初始化没有元素的情况。
      因为用一级指针的话,如果我们为数组赋一个初值,如果我们赋的是0,一般是没有办法和初值区分,因为有可能元素也是0,但指针没有元素,可以用空NULL表示,所以用二级指针可以为每一个一级指针置空*/
      struct    pair **table;
      int   sizeHash;        //记录当前哈希数组的哈希地址个数
      int     divisor;          //y=x%divisor
};

struct     hashTable* createHash(int   divisor)
{
       struct    hashTable* hash = (struct     hashTable*)malloc(sizeof(struct    hashTable));
       hash->sizeHash = 0;
       hash->divisor = divisor;
       hash->table = (struct     pair**)malloc(sizeof(struct   pair)*hash->divisor);
       /*(struct    pair)*hash->divisor是存放除数,是(struct     pair)乘以hash->divisor,然后hash->table就有这么大的内存,所以产生了多个hashi->divisor一级指针*/
       /*都是一级指针,方便初始化*/
       /*二维数组申请了内存,存一级指针,一级指针等于NULL,一级指针变一维数组*/
       for(int    i = 0; i< divisor ; i++)
       {
                 hash->table[i] = NULL;
        }
        return    hash;
}


/*插入,要找到正确的地址,才能正确的插入,通过关键字first去查找*/
int   search(struct   hashTabkle* hash,int   first)
{
       /*本来的地址(即哈希下标)可以通过构造函数求出来*/
       /*找一个可以使用的地址,直接返回*/
       int     pos=first%(hash->divisor);/*但是他不一定是我们要的地址(哈希冲突),所以要判断一下,当前地址是空的才能使用*/
       int    curPos = pos;
       do
       {
           /*判断如果哈希表里面没有元素,或者当前哈希地址正好等于first,意味着当前位置是可以使用的,这时候直接返回当前下标*/
           /*找一个可以使用的地址,直接返回*/
           if(hash->table[curPos] == NULL||hash->table[curPos]->first == first)
           /*这里的first是修改hash->table[curPos]中的second[]*/
           {
               return  curPos; 
           }
           /*(curpos+1)是每次挪动一位去求哈希地址,否则下标不会变动*/
           curPos = (curPos + 1)%(hash->divisor);
       }while(curPos!=pos);/*判断当前下标不等于原来下标,如果是就等于没有位置了*/
       /*curPos会一直往下走,但是它会走一个循环,循环到有元素的时候就会停下来,例   11->19->20->21  停止*/
       return  curPos;      
}


//插入
void    insertHash(struct    hashTable* hash, struct    pair   data)
{ 
	int  pos = search(hash,data,.first);
	if(hash->table[pos] == NULL)
	{
	     /*为table[]一级指针分配内存*/
	     hash->table[pos] =  (struct   pair*)malloc(sizeof(struct  pair));
	     /*因为是结构体类型,数据不能直接拷贝,所以要用memcpy内存拷贝的方式*/
	     memcpy(hash->table[pos],&data,sizeof(struct  pair));
	     hash->sizeHash++;
	} 
	/*另一种情况表示哈希冲突*/
	else
	{
	     if(hash->table[pos]->first == data.first)
	     {
	           /*把原来的值复制成新的值*/
	           strcpy(hash->table[pos]->second, data.second);  
	     }
	     else
	     {
	          printf("表满了,无法插入\n");
	          return; 
	     }
	}
}


void   printList(struct   hashTable* hash)
{
     fof(int   i = 0 ; i < hash->divisor ; i++)
     {
          if(hash->table[i]==NULL)
          {
               printf("NULL"); 
          } 
          else
          (
                printf("%d  %s\n",hash->table[i]->first,hash->table[i]->second); 
          )
     }
}


int   main()
{
       struct    hashTable* hash = createHash(10);
       struct  pair   array[5] = {1,"k",2,"a",3,"b"};
       for(int   i=0;i<5;i++)
       { 
            insertHash(hash,array[i]);
	   }
	   printList(hash);

      system("pause");
      return   0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值