头歌:哈希表基本操作

哈希表基本操作答案

  • 第一关:采用除留余数法加线性探测法建立哈希表
  • 第二关:在采用除留余数法加线性探测法建立的哈希表中查找数据
  • 第三关:采用除留余数法加链地址法建立哈希表
  • 第四关:在采用除留余数法加链地址法建立的哈希表中删除数据

    第一关:采用除留余数法加线性探测法建立哈希表

    #include"stdio.h"
    #include"stdlib.h"
    #define NULL_KEY -1 // -1为无记录标志
    #define SUCCESS 1
    #define UNSUCCESS 0
    #define DUPLICATE -1
    #define N 100  // 数据元素个数
    typedef int KeyType; // 设关键字域为整型
    struct ElemType // 数据元素类型
    { KeyType key;     
    };
    struct HashTable
    { ElemType *elem; // 数据元素存储基址,动态分配数组
       int count; // 当前数据元素个数
       int sizeindex; // sizeindex为哈希表表长
    };
    // 哈希函数的基本操作函数
    void InitHashTable(HashTable &H);    // 构造一个空的哈希表
    void DestroyHashTable(HashTable &H);  // 哈希表H存在。操作结果:销毁哈希表H
    unsigned Hash(KeyType K);    // 哈希函数
    void collision(int &p,int d); // 线性探测再散列
    int SearchHash(HashTable H,KeyType K,int &p,int &c);  // 在开放定址哈希表H中查找关键码为K的元素
    int InsertHash(HashTable &H,ElemType e); // 查找不成功时插入数据元素e到开放定址哈希表H中   
    void TraverseHash(HashTable H,void(*Vi)(int));
    void print(int p);
     int m=0;   // 全局变量, H(key) = key % m
     int main()
     { ElemType r[N]={0};
       HashTable h;
       int i,p,n;
       int j;
       KeyType k;    
       InitHashTable(h);
       scanf("%d",&m); // H(key) = key % m
       scanf("%d",&n); // 数据的个数    
       for(i=0;i scanf("%d",&r[i].key);     
       }
       for(i=0;i // 插入前N-1个记录
         j=InsertHash(h,r[i]);    
       }
       //printf("按哈希地址的顺序遍历哈希表:\n");
       TraverseHash(h,print);   
       DestroyHashTable(h);
     }
     // 哈希函数的基本操作函数
    void InitHashTable(HashTable &H)
     { // 操作结果:构造一个空的哈希表
      int i;
      H.count=0; // 当前元素个数为0  
      scanf("%d",&H.sizeindex ); // 哈希表存储容量
      H.elem=(ElemType*)malloc(H.sizeindex*sizeof(ElemType));  
      for(i=0;i // 初始条件:哈希表H存在。操作结果:销毁哈希表H
       free(H.elem);
       H.elem=NULL;
       H.count=0;
       H.sizeindex=0;
     }
    unsigned Hash(KeyType K)
    { // 一个简单的哈希函数(m为全局变量)
        /********** Begin **********/
        return K%m;
       /********** End **********/    
    }
    void collision(int &p,int d) // 线性探测再散列
    { // 开放定址法处理冲突
        /********** Begin **********/
        p=(p+1)%m;
       /********** End **********/
     }
    int SearchHash(HashTable H,KeyType K,int &p,int &c)
    { // 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
       // 元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS
       // c用以计冲突次数,其初值置零,供建表插入时参考。
       /********** Begin **********/
      p=Hash(K); // 求得哈希地址
      while( H.elem[p].key!=NULL_KEY && K!= H.elem[p].key )
      { // 该位置中填有记录.并且关键字不相等
        c++;
        if(c // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;
      // 若冲突次数过大,则重建哈希表,算法9.18
      /********** Begin **********/
      int c,p;
      c=0;
      if(SearchHash(H,e.key,p,c)) // 表中已有与e有相同关键字的元素
        return DUPLICATE;
      else if(c // 插入e
        H.elem[p]=e;
        ++H.count;
        return SUCCESS;
      }
      else
        return UNSUCCESS;
      /********** End **********/
     }
     void TraverseHash(HashTable H,void(*Vi)(int))
     { // 按哈希地址的顺序遍历哈希表
        printf("哈希地址0~%d\n",H.sizeindex-1);
        for(int i=0;i printf("%d\t",p);
    }
    

    第二关:在采用除留余数法加线性探测法建立的哈希表中查找数据

    #include"stdio.h"
    #include"stdlib.h"
    #define NULL_KEY -1 // -1为无记录标志
    #define SUCCESS 1
    #define UNSUCCESS 0
    #define DUPLICATE -1
    #define N 100  // 数据元素个数
    typedef int KeyType; // 设关键字域为整型
    struct ElemType // 数据元素类型
    { KeyType key;     
    };
    struct HashTable
    { ElemType *elem; // 数据元素存储基址,动态分配数组
       int count; // 当前数据元素个数
       int sizeindex; // sizeindex为哈希表表长
    };
    // 哈希函数的基本操作函数
    void InitHashTable(HashTable &H);    // 构造一个空的哈希表
    void DestroyHashTable(HashTable &H);  // 哈希表H存在。操作结果:销毁哈希表H
    unsigned Hash(KeyType K);    // 哈希函数
    void collision(int &p,int d); // 线性探测再散列
    int SearchHash(HashTable H,KeyType K,int &p,int &c);  // 在开放定址哈希表H中查找关键码为K的元素
    int InsertHash(HashTable &H,ElemType e); // 查找不成功时插入数据元素e到开放定址哈希表H中   
    void TraverseHash(HashTable H,void(*Vi)(int));
    void print(int p);
    int Find(HashTable H,KeyType K,int &p);
     int m=0;   // 全局变量, H(key) = key % m
     int main()
     { ElemType r[N]={0};
       HashTable h;
       int i,p,n;
       int j;
       KeyType k;    
       InitHashTable(h);
       scanf("%d",&m); // H(key) = key % m
       scanf("%d",&n); // 数据的个数    
       for(i=0;i scanf("%d",&r[i].key);     
       }
       for(i=0;i // 插入前N-1个记录
         j=InsertHash(h,r[i]);    
       }
       //printf("按哈希地址的顺序遍历哈希表:\n");
       TraverseHash(h,print);
       //printf("请输入待查找记录的关键字: ");
       scanf("%d",&k);
       j=Find(h,k,p);
       if(j==SUCCESS)
         { printf("查找成功:");  
           print(h.elem[p].key);
         }
         
       else
         printf("查找失败\n");   
       DestroyHashTable(h);
     }
     // 哈希函数的基本操作函数
    void InitHashTable(HashTable &H)
     { // 操作结果:构造一个空的哈希表
      int i;
      H.count=0; // 当前元素个数为0  
      scanf("%d",&H.sizeindex ); // 哈希表存储容量
      H.elem=(ElemType*)malloc(H.sizeindex*sizeof(ElemType));  
      for(i=0;i // 初始条件:哈希表H存在。操作结果:销毁哈希表H
       free(H.elem);
       H.elem=NULL;
       H.count=0;
       H.sizeindex=0;
     }
    unsigned Hash(KeyType K)
    { // 一个简单的哈希函数(m为全局变量)
      return K%m;
    }
    void collision(int &p,int d) // 线性探测再散列
    { // 开放定址法处理冲突
      p=(p+1)%m;
     }
    int SearchHash(HashTable H,KeyType K,int &p,int &c)
    { // 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
      // 元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS
      // c用以计冲突次数,其初值置零,供建表插入时参考。
      p=Hash(K); // 求得哈希地址
      while( H.elem[p].key!=NULL_KEY && K!= H.elem[p].key )
      { // 该位置中填有记录.并且关键字不相等
        c++;
        if(c // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;
      // 若冲突次数过大,则重建哈希表 
      int c,p;
      c=0;
      if(SearchHash(H,e.key,p,c)) // 表中已有与e有相同关键字的元素
        return DUPLICATE;
      else if(c // 插入e
        H.elem[p]=e;
        ++H.count;
        return SUCCESS;
      }
      else
        return UNSUCCESS;
     }
     void TraverseHash(HashTable H,void(*Vi)(int))
     { // 按哈希地址的顺序遍历哈希表
        printf("哈希地址0~%d\n",H.sizeindex-1);
        for(int i=0;i printf("%d\t",p);
    }
    int Find(HashTable H,KeyType K,int &p)
    { // 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
      // 元素在表中位置,并返回SUCCESS;否则,返回UNSUCCESS
      /********** Begin **********/ 
    	p=Hash(K);
      int c=0;
      while(H.elem[p].key!=NULL_KEY&&H.elem[p].key!=K)
      { c++;
        printf("哈希地址为%d,第%d次冲突\n",p,c);
        if(c collision(p,c);
        }
      }
      c++;
      if(H.elem[p].key==K)
      { printf("哈希地址为%d,第%d次查找成功\n",p,c);
        return SUCCESS;
      }
      else
      { printf("哈希地址为%d,第%d次查找为空\n",p,c);
      return UNSUCCESS;
      }
      /********** End **********/
     }
    

    第三关:采用除留余数法加链地址法建立哈希表

    #include #include #define N 20  // 数据元素个数
    typedef int KeyType; // 设关键字域为整型
    struct ElemType // 数据元素类型
    { KeyType key;     
    };
    typedef struct Node { //链地址,其实这个指针就是链表
    	ElemType r;
    	struct Node* next;
    }Node;
    typedef struct {Node** rcd;								//(指向指针的指针)存放指针的数组
    	int size;								//哈希表的容量
    	int count;								//当前表中含有的记录个数	
    }HashTable;
    int InitHash(HashTable& H, int size);	//初始化哈希表
    int DestroyHash(HashTable& H);									//销毁哈希表
    Node* SearchHash(HashTable H, KeyType key);							//查找
    int InsertHash(HashTable& H, ElemType e);							//插入
    int DeleteHash(HashTable& H, KeyType key, ElemType& e);			//删除
    void HashTraverse(HashTable H);										//遍历
    unsigned Hash(KeyType K,int m);
    int m,n,i,j; 
    int main()
    { HashTable h;
    	KeyType k;
    	ElemType r[N]={0};   
       scanf("%d",&m); // H(key) = key % m
       scanf("%d",&n); // 数据的个数  
       InitHash(h,m);  
       for(i=0;i scanf("%d",&r[i].key);     
       }
       for(i=0;i // 插入前N-1个记录     
    		InsertHash(h, r[i]);		
       }
        printf("采用链地址法得到的哈希表为:\n");   	
    	HashTraverse(h);	
    	DestroyHash(h);
    }
    unsigned Hash(KeyType K,int m)
    { // 一个简单的哈希函数
      return K%m;
    }
    int InitHash(HashTable& H, int size)
    {H.rcd = (Node**)malloc(size*sizeof(Node*));
    	if (H.rcd != NULL)
    	{for (int i = 0; i < size; i++)
    		{H.rcd[i] = NULL;			
    		}
    		H.size = size;		
    		H.count = 0;
    		return 1;
    	}
    	else 
    	{return 0;
    	}
    }
    int DestroyHash(HashTable& H)
    {if (H.rcd != NULL)
    	{Node* np, * nt;
    		for (int i = 0; i < H.size; i++)
    		{np = H.rcd[i];
    			while (np != NULL)
    			{nt = np;
    				np = np->next;
    				free(nt);
    			}
    		}
    		H.size = 0;
    		H.count = 0;
    		return 1;
    	}
    	else
    	{return 0;
    	}
    }
    Node* SearchHash(HashTable H, KeyType key)
    {/*********BEGIN*********/
    	int p;
        Node* np;
        p = Hash(key,H.size);    
        np = H.rcd[p];
        while (np)
        { if(key == np->r.key)
                    return np ;
            np = np->next;
        }
        return NULL;
    	/**********END**********/
    }
    int InsertHash(HashTable& H, ElemType e)
    { /*********BEGIN*********/	
    	int p;
        Node* np;
        np = SearchHash(H, e.key);
        if (np == NULL)
        { p = Hash(e.key,H.size);
            np = (Node*)malloc(sizeof(Node));
            np->r = e;
            np->next = H.rcd[p];
            H.rcd[p] = np;
            H.count++;
            return 1;
        }
        else
        { return 0;
        }
    }
    	/**********END**********/
    void HashTraverse(HashTable H)
    {if (H.rcd != NULL)
    	{Node* np, * nq;
    		for (int i = 0; i < H.size; i++)
    		{printf("%d:  ", i);
    			if (H.rcd [i])
    			{printf("%d  ",H.rcd [i]->r .key);
    				Node* curr=H.rcd [i]->next;
    				while (curr) { printf("-> %d  ", curr->r.key);
                    curr=curr->next;
    				}
    				printf("\n");
    			}
    			else 
    				printf("-\n");
    		}
    	}
    }
    

    第四关:在采用除留余数法加链地址法建立的哈希表中删除数据

    #include #include #define N 20  // 数据元素个数
    typedef int KeyType; // 设关键字域为整型
    struct ElemType // 数据元素类型
    { KeyType key;     
    };
    typedef struct Node { //链地址,其实这个指针就是链表
        ElemType r;
        struct Node* next;
    }Node;
    typedef struct { Node** rcd;                                //(指向指针的指针)存放指针的数组
        int size;                                //哈希表的容量
        int count;                                //当前表中含有的记录个数    
    }HashTable;
    int InitHash(HashTable& H, int size);    //初始化哈希表
    int DestroyHash(HashTable& H);                                    //销毁哈希表
    Node* SearchHash(HashTable H, KeyType key);                            //查找
    int InsertHash(HashTable& H, ElemType e);                            //插入
    int DeleteHash(HashTable& H, KeyType key, ElemType& e);            //删除
    void HashTraverse(HashTable H);                                        //遍历
    unsigned Hash(KeyType K,int m);
    int main()
    { HashTable h;
        KeyType k;
        ElemType r[N]={0},e;   
        int m,n,i,j;  
       scanf("%d",&m); // H(key) = key % m
       scanf("%d",&n); // 数据的个数  
       InitHash(h,m);  
       for(i=0;i scanf("%d",&r[i].key);     
       }
       for(i=0;i // 插入前N-1个记录     
            InsertHash(h, r[i]);        
       }
        printf("采用链地址法得到的哈希表为:\n");       
        HashTraverse(h);    
       //printf("请输入要删除的整数值:\n");
       scanf("%d",&k);    
      if ( DeleteHash(h, k, e) )
       { printf("删除元素后哈希表为:\n");       
            HashTraverse(h);
       }
       else
            printf("删除元素失败。\n"); 
        DestroyHash(h);
    }
    unsigned Hash(KeyType K,int m)
    { // 一个简单的哈希函数
      return K%m;
    }
    int InitHash(HashTable& H, int size)
    { H.rcd = (Node**)malloc(size*sizeof(Node*));
        if (H.rcd != NULL)
        { for (int i = 0; i < size; i++)
            { H.rcd[i] = NULL;            
            }
            H.size = size;        
            H.count = 0;
            return 1;
        }
        else 
        { return 0;
        }
    }
    int DestroyHash(HashTable& H)
    { if (H.rcd != NULL)
        { Node* np, * nt;
            for (int i = 0; i < H.size; i++)
            { np = H.rcd[i];
                while (np != NULL)
                { nt = np;
                    np = np->next;
                    free(nt);
                }
            }
            H.size = 0;
            H.count = 0;
            return 1;
        }
        else
        { return 0;
        }
    }
    Node* SearchHash(HashTable H, KeyType key)
    { int p;
        Node* np;
        p = Hash(key,H.size);    
        np = H.rcd[p];
        while (np)
        { if(key == np->r.key)
                    return np ;
            np = np->next;
        }
        return NULL;
    }
    int InsertHash(HashTable& H, ElemType e)
    { int p;
       Node* np;
       np = SearchHash(H, e.key);
       if (np == NULL)
       { p = Hash(e.key,H.size);
           np = (Node*)malloc(sizeof(Node));
           np->r = e;
           np->next = H.rcd[p];
           H.rcd[p] = np;
           H.count++;
           return 1;
       }
       else
       { return 0;
       }
    }
    int DeleteHash(HashTable& H, KeyType key, ElemType& e)
    { /*********BEGIN*********/    
       Node* n;
       n = SearchHash(H, key);
       if (n != NULL)
       { int p = Hash(key,H.size);
           Node* np, * nq;
           np = H.rcd[p];
           nq = NULL;
           while (np != NULL)
           { if (np->r.key != key)
               { nq = np;
                   np = np->next;
               }
               else
               { e = np->r;
                   if (nq == NULL)//表头
                   { H.rcd[p] = np->next;
                   }
                   else//不是表头
                   { nq->next = np->next;
                   }
                   break;
               }
           }
           H.count--;
           free(np);
           return 1;
       }
       else
       { return 0;
       }
       /**********END**********/
    }
    void HashTraverse(HashTable H)
    { if (H.rcd != NULL)
        { Node* np, * nq;
            for (int i = 0; i < H.size; i++)
            { printf("%d:  ", i);
                if (H.rcd [i])
                { printf("%d  ",H.rcd [i]->r .key);
                    Node* curr=H.rcd [i]->next;
                    while (curr) { printf("-> %d  ", curr->r.key);
                    curr=curr->next;
                    }
                    printf("\n");
                }
                else 
                    printf("-\n");
            }
        }
    }