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

typedef struct   //哈希
{
    int key;  //哈希地址关键字
    int hi;    //哈希冲突次数
}DataType;

typedef struct  
{
    DataType *data;
    int tableSize;     //哈希长度
    int curSize;       //关键字长度
}HashTable;


//创建哈希表,m为哈希长度,p为用于取模,hash[]处理的数组,n为关键字长度
void CreateHashTable(HashTable *H,int m,int p,int hash[],int n)
{
    int i,addr;
    int sum=0;
    
    (*H).data = (DataType*)malloc(sizeof(DataType));
    if ( !(*H).data )
    {
        exit(-1);
    }
    
    for ( i=0 ; i<m ; i++ )  //初始化数组,未访问的关键字为-1,冲突次数为0
    {
        (*H).data[i].key = -1;
        (*H).data[i].hi = 0;
    }
    
    for ( i=0 ; i<m ; i++ )   //哈希地址映射过程
    {
        addr = hash[i]%p;
        
        if ( (*H).data[addr].key == -1 )  //关键字为访问过
        {
            (*H).data[addr].key = hash[i];
            (*H).data[addr].hi = 0;
        }
        else   //访问过利用线性在哈希分地址
        {
            do
            {
                addr = (addr+1)%m;
                sum++;
            }while ( (*H).data[addr].key != -1 );
            (*H).data[addr].key = hash[i];
            (*H).data[addr].hi = sum+1;
        }
    }
    (*H).tableSize = m;
    (*H).curSize = n;
    
}


void DisplayHashTable(HashTable H,int m)  //输出哈希表
{
    int i;
    
    printf("输出哈希地址:\n");
    for ( i=0 ; i<m ; i++ )
    {
        printf("%-5d",i);
    }
    printf("\n");
    
    printf("输出关键字:\n");
    for ( i=0 ; i<m ; i++ )
    {
        printf("%-5d",H.data[i].key);
    }
    printf("\n");
    
    printf("输出冲突次数:\n");
    for ( i=0 ; i<m ; i++ )
    {
        printf("%-5d",H.data[i].hi);
    }
    printf("\n");
}


int SearchKey(HashTable H,int k)   //关键字查找
{
    int d,d1,m;
    
    m = H.tableSize;
    d = d1 = k%m;
    
    while ( H.data[d].key != -1 )
    {
        if ( H.data[d].key == k )
        {
            return d;
        }
        else
        {
            d = (d+1)%m;
        }
        
        if ( d == d1 )
        {
            return -1;
        }
    }
    return -1;
}


int main(void)
{
   
    int hash[]={23,99,13,16,76,97,0,6};
    int m=8,p=8,n=8;
    int k,pos;

    HashTable H;
    CreateHashTable(&H,m,p,hash,n);
    
    DisplayHashTable(H,m);
    
    k=99;
    pos = SearchKey(H,k);
    
    printf("%d在哈希表中的关键字地址是:%d\n",k,pos);


    return 0;
}