结构推理 试根据全年级学生的姓名,构造一个散列表,选择适当的散列函数和解决碰撞方法,设计并实现插入、删除和查找算法,统计碰撞发生的次数(用拉链法解决碰撞时负载因子取2,用开地址法时取1/2)。
【正确答案】采用拉链法。
   (1)数据结构
   struct ZipNode;
   typedef struct ZipNode*PZipNode;
   struct ZipNode{
     char key[30];
     char*value;
     PZipNode link;
   };
   struct ZipHashDic{
     PZipNode linklist[BasicLong];
   };
   typedef struct ZipHashDic。PZipHashDic;
   (2)算法
   1)创建
   PZipHashDic create(){
       int i:
     PZipHashDic s;
     s=(PZipHashDic)malloc(sizeof(struct ZipHashDic));
     if(s!=NULL)
       for(i=0;i<BasicLong;i++)
         s->linklist[i]=NULL;
     return s;
   }
   int h(char key[]){
       return(key[0]-'A')/%26;
   }
   2)检索
   /*如果找到则返回指向该元素的指针值,否则返回空指针;a表示在第几行,b表示为第几个,如果没有就同时为0*/
   PZipNode find(PZipHashDic s,char key[],int*a,int*b){
       PZipNode t;
       int d,i=1;
       d=h(key);
       t=s->linklist[d];
       while(t!=NULL){    /*检索*/
         if(strcmp(t->key,key)==0){
           *a=d+1:
           *b=i:
           return t:
         }
         t=t->link;
         i++:
       }
       *a=0;
       *b=0;    /*没找到*/
       return t:
   }
   3)插入
   /*same保存碰撞次数*/
   void insert(PZipHashDic s,char key[],int*same){
       PZipNode t,v;
       int d;
       d=h(key);
       t=(PZipNode)malloc(sizeof(struct ZipNode));
       if(t==NULL){
           printf("Out of space!\n");
           return;
       }
       strcpy(t->key,key);
       t->link=NULL;
       v=s->linklist[d];
       if(v==NULL){
           s->linklist[d]=t;
           return;
       }
       else{
           (*same)++;    /*这时已经和该链的第一个结点碰撞了*/
           while(v->link!=NULL){
         if(v->key==key){
               free(t);
               return;
             }
             v=v->link;
             (*same)++;
           }
           if(v->key==key){
           /*如果恰好该链表的最后一个元素与要插入的相同*/
               free(t);
               return;
           }
           v->link=t;
       }
   }
   4)删除
   void deletekey(PZipHashDic s,char key[]){
         PZipNode t,v;
         int d=h(key);
         if(s->linklist[d]==NULL)return;
         t=s->linklist[d];
         if(strcmp(t->key,key)==0){  /*如果要删除第一个*/
           v=t;
           s->linklist[d]=t->link;
           free(v);
           return;
       }
       while(t->link!=NULL){    /*其他*/
           if(strcmp(t->link->key,key)==0){
             v=t->link;
             t->link=t->link->link;
             free(v);
             return;
           }
         t=t->link;
       }
   }
【答案解析】