欢迎使用CSDN-markdown编辑器

在做OJ题的时候,会经常遇到处理大量字符串输入,并查找某字符串是否在字符串数据库内,使用最简单最暴力的方法就是全局搜索,一个字符串一个字符串的比较,如果遇到较庞大的字符串数据库时,搜索将花费大量的时间,使用Hash方法可以大大降低搜索次数,提高程序的运行效率。
Hash方法的关键是在Hash函数算法上,在各个领域有大量的科研人员对Hash算法进行研究。Hash算法的研究已经超出了笔者的能力范围,也不再本文的表示范围内。
为了对字符串进行压缩映射,需要使用Hash函数对字符串进行处理,常用的字符串Hash算法有:BKDRHash、APHash、DJBHash等经典算法,本文的实现中采用了BKDRHash算法,因为它实现简单易懂,在字符串Hash中也有很好的效果。
BKDRHash算法中需要关注的几个点是seed种子数字的选择,算法给出了31、131、1313、13131、131313等数值供选择,在一般的应用中31和131已经足够了,本文的实现中采用了131数值作为种子数,还有一个点是HashTable长度的选择,因为长度直接关系到你的Hash表的容量大小,即字符串可以映射到的范围,长度的选择应根据实际的应用场景进行选择。

//定义的装字符串的节点,使用链表是为了处理冲突
struct Node
{
char *str;
Node *next;
};

const unsigned int wordTotalNum = 10000; //根据实际应用场景选择hash表的长度

//字符串哈希函数
//BKDR Hash Function
unsigned int BKDRHash(const char *str)
{
unsigned int seed = 131; //seed可以取31,131,1313,13131,131313,etc…
unsigned int hash = 0;

while (*str)
{
    hash = hash * seed + (*str++);
}


return (hash & wordTotalNum);

}

//创建哈希表,使用函数指针作为入参是为了适配不同的Hash算法
void AddHashTable(Node **hashTable, const char *inputStr, unsigned int (HashFunction)(const char *str))
{
unsigned int tableIndex = HashFunction(inputStr);

if (NULL == hashTable[tableIndex])
{
    hashTable[tableIndex] = new Node;
    memset(hashTable[tableIndex], 0, sizeof(Node));
    hashTable[tableIndex]->str = new char[strlen(inputStr) + 1];
    memcpy(hashTable[tableIndex]->str, inputStr, strlen(inputStr) + 1);
}
else
{
    //产生冲突
    Node *pTemp = hashTable[tableIndex];
    while (NULL != pTemp->next)
    {
        //此处字符串比较不能用memcmp和strncmp函数,因为无法避免inputStr和pTemp的前
        //一段字符串完全相同,只是字符串长度不一样。用strcmp进行比较,可以避免这种情况
        //但是由于内存比较操作没有长度作为参数去限制,必须得保证两个字符串都满足char字符串
        //的要求,必须以'\0'结束!
        if (0 == strcmp(inputStr, pTemp->str))
        {
            return;
        }
        pTemp = pTemp->next;
    }

    pTemp->next = new Node;
    pTemp = pTemp->next;
    memset(pTemp, 0, sizeof(Node));

    pTemp->str = new char[strlen(inputStr) + 1];
    memcpy(pTemp->str, inputStr, strlen(inputStr) + 1);
}

}

bool SearchHashTable(Node **hashTable, const char *inputStr, unsigned int(HashFunction)(const char *str))
{
unsigned int tableIndex = HashFunction(inputStr);
if (NULL == hashTable[tableIndex])
{
//没查找到输入字符串
return false;
}
else
{
Node *pTemp = hashTable[tableIndex];
while (NULL != pTemp)
{
if(0 == strcmp(pTemp->str, inputStr))
{
return true;
}
else
{
pTemp = pTemp->next;
}
}
return false;
}
}

void DeleteHashTable(Node **hashTable)
{
for (size_t i = 0; i < wordTotalNum; ++i)
{
if (NULL != hashTable[i])
{
Node *pTemp = hashTable[i];
while (NULL != pTemp)
{
Node *pNext = pTemp->next;
delete []pTemp->str;
delete pTemp;
pTemp = pNext;
}
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值