散列表实现

基本思想

散列表的数据结构可以看作是包含有关关键字的具有固定大小的数组。假设这个数组(hash表)的大小是tableSize,那么我们可以把数据按照从0-tableSize-1的键值来存放,数据通过hash来映射不同的键值。这个映射就叫做散列函数(hash function),理想情况下它应该运算简单并且应该保证任何两个不同的关键字映射到不同的单元。不过,数据很多的情况下,这基本上是不可能的,不过可以通过一些方法来解决出现冲突的情况,比如使用分离链接法。

分离链接法

基本思想是通过链表的形式,把hash到相同键值的数据连接起来。
可参考下面的代码

#include <stdio.h>
#include <stdlib.h>
#define MinTableSize  10

int Hash(const int key, int tableSize)
{
    return key % tableSize;
}
struct List
{
    int val;
    struct List*next;
};
typedef struct List ListNode;
struct hashtable
{
    int tableSize;
    ListNode **theLists;
};
typedef struct hashtable HashTable;

//获得合适的模的大小
int getModuleSize(int tableSize)
{
    int i;
    if(tableSize%2 == 0)
        tableSize++;

    i = 3;
    while(i*i <= tableSize)
    {
        if(tableSize%i == 0)
        {
            tableSize = tableSize + 2;
            i = 3;
        }
        else{
            i+=2;
        }

    }
    return tableSize;

}
//初始化hash表
HashTable *InitalizeTable(int TableSize)
{
    HashTable *hashTable;
    int i = 0;

    if(TableSize < MinTableSize)
    {
        perror("Table size too small");
        return NULL;
    }

    //allocate tableSize
    hashTable = malloc(sizeof(HashTable));
    if(NULL== hashTable)
        perror("Out of space");
    hashTable->tableSize = getModuleSize(TableSize);
    hashTable->theLists = malloc(sizeof(ListNode)*hashTable->tableSize);
    if(hashTable->theLists == NULL)
        perror("Out of space");
    /* allocate list headers */
    printf("hashTable size : %d\n", hashTable->tableSize);
    for(i = 0; i < hashTable->tableSize; ++i)
    {
        hashTable->theLists[i] = malloc(sizeof(ListNode));
        if(hashTable->theLists[i] == NULL)
            perror("out of space");
        else
            hashTable->theLists[i]->next = NULL;
    }
    return hashTable;
}
//从hash表中找到key
ListNode* Find(int key, HashTable*H)
{
    ListNode* p;
    p = H->theLists[Hash(key, H->tableSize)];

    while(p != NULL)
    {
        if(p->val == key)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}
//插入key
void Insert(int key, HashTable* H)
{
    ListNode* Pos, *NewCell;
    ListNode *L;
    Pos = Find(key, H);
    if(Pos == NULL)
    {
        NewCell = malloc(sizeof(ListNode));
        if(NULL == NewCell)
            printf("out of space\n");
        else
        {
            L = H->theLists[Hash(key, H->tableSize)];
            NewCell->next = L->next;
            NewCell->val = key;
            L->next = NewCell;
        }
    }
}
//打印hash表
void printHashTable(HashTable *hashTable)
{
    int key = 0;
    ListNode *pNode;

    for(key = 0; key < hashTable->tableSize; ++key)
    {
        pNode = hashTable->theLists[Hash(key, hashTable->tableSize)];
        pNode = pNode->next;
        printf("+------------+\n");
        printf("hashTable[%d]",key);
        while(pNode != NULL)
        {
            printf("->%d",pNode->val);
            pNode = pNode->next;
        }
        printf("\n+------------+\n");
    }
}
//单元测试
void testHash()
{
    int tableSize = 12;
    ListNode *nodeBeToFound;
    HashTable* H = InitalizeTable(tableSize);
    if(H == NULL)
    {
        printf("Func InitalizeTable return NULL\n");
        return;
    }
    int i = 0;
    int size = 5;
    int goal = 5;
    for(i = 1; i <= size; ++i)
    {
        Insert(i*i, H);
        //printf("%d:%d\n",i*i, Hash(i*i,10));
    }
    printHashTable(H);
    nodeBeToFound = Find(25,H);
    if(nodeBeToFound != NULL)
    printf("node found is %d\n",nodeBeToFound->val);

}
void main()
{
    testHash();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值