散列表——分离链接法
2017-05-05 13:24
323 查看
散列表由一个二级指针构成,二级指针的每一个节点指向一个单链表。
向散列表中插入电影《云图》里的一句台词:“Yesterday my life was headed in one direction, today it is headed in another. Yesterday I believe that I could not do, today but I do.” 为了方便,插入的单词均为小写字母。
散列函数为单词首字母和字母a的差值:h(key) = key[0] - 'a', 散列表大小定义为26个。重复出现的单词只插入一次。
头文件定义如下,单链表节点char data[10]正好足够储存最长的单词"yesterday\0"。
禁止拷贝构造和赋值运算符。
hashFunc()函数和findKey()函数声明为私有,作为类内部使用,不向外提供接口。
hashlist.cpp定义如下。
构造函数完成数据成员的初始化。
析构函数先删除每个节点所指的单链表,再删除散列表。
findKey()函数返回key所在的链表节点的指针,没找到返回NULL。
insertKey()函数需要判断三种情况:
1.散列表节点所指的链表中已经储存有该单词,直接return;
2.散列表节点为空,指向新申请的链表节点;(此时不能使用p->next,会发生segmentation fault)
3.散列表节点不为空,接至所指链表的尾节点。
测试代码如下。
运行结果如下,valgrind检测无异常。
向散列表中插入电影《云图》里的一句台词:“Yesterday my life was headed in one direction, today it is headed in another. Yesterday I believe that I could not do, today but I do.” 为了方便,插入的单词均为小写字母。
散列函数为单词首字母和字母a的差值:h(key) = key[0] - 'a', 散列表大小定义为26个。重复出现的单词只插入一次。
头文件定义如下,单链表节点char data[10]正好足够储存最长的单词"yesterday\0"。
禁止拷贝构造和赋值运算符。
hashFunc()函数和findKey()函数声明为私有,作为类内部使用,不向外提供接口。
#ifndef _HASHLIST_H_ #define _HASHLIST_H_ struct ListNode { char data[10]; ListNode* next; }; class HashList { public: HashList(int listsize); ~HashList(); private: HashList(const HashList& h); HashList& operator=(const HashList& h); public: void insertKey(const char* key); void print(); private: ListNode* findKey(const char* key); int hashFunc(const char* key); private: int m_listsize; ListNode** m_hashlist; }; #endif // _HASHLIST_H_
hashlist.cpp定义如下。
构造函数完成数据成员的初始化。
析构函数先删除每个节点所指的单链表,再删除散列表。
findKey()函数返回key所在的链表节点的指针,没找到返回NULL。
insertKey()函数需要判断三种情况:
1.散列表节点所指的链表中已经储存有该单词,直接return;
2.散列表节点为空,指向新申请的链表节点;(此时不能使用p->next,会发生segmentation fault)
3.散列表节点不为空,接至所指链表的尾节点。
#include "hashlist.h" #include <string.h> #include <iostream> HashList::HashList(int listsize) :m_listsize(listsize) { m_hashlist = new ListNode*[listsize]; memset(m_hashlist, 0, listsize * sizeof(ListNode*)); } HashList::~HashList() { for(int i = 0; i < m_listsize; i++) { while(m_hashlist[i] != NULL) { ListNode* t = m_hashlist[i]; m_hashlist[i] = m_hashlist[i]->next; delete t; } } delete[] m_hashlist; } int HashList::hashFunc(const char* key) { return key[0] - 'a'; } ListNode* HashList::findKey(const char* key) { ListNode* p = m_hashlist[hashFunc(key)]; while(p != NULL && (strcmp(p->data, key) != 0)) { p = p->next; } return p; } void HashList::insertKey(const char* key) { if(findKey(key) != NULL) { return; } ListNode* t = new ListNode; memset(t, 0, sizeof(ListNode)); strcpy(t->data, key); t->next = NULL; int i = hashFunc(key); if(m_hashlist[i] == NULL) { m_hashlist[i] = t; } else { ListNode* p = m_hashlist[i]; while(p->next != NULL) { p = p->next; } p->next = t; } } void HashList::print() { for(int i = 0; i < m_listsize; i++) { std::cout << "hashlist " << i << " : "; for(ListNode* p = m_hashlist[i]; p != NULL; p = p->next) { std::cout << p->data << "->"; } std::cout << "NULL" << std::endl; } }
测试代码如下。
#include "hashlist.h" int main() { const char *str[] = {"yesterday", "my", "life", "was", "headed", "in", "one", "direction", "today", "it", "is", "headed", "in", "another", "yesterday", "i", "believe", "that", "i", "could", "not", "do", "today", "but", "i", "do"}; HashList h(26); for (unsigned int i = 0; i < sizeof(str)/sizeof(str[0]); i++) { h.insertKey(str[i]); } h.print(); return 0; }
运行结果如下,valgrind检测无异常。
相关文章推荐
- 分离链接散列表
- 数据结构与算法分析-分离链接散列表的实现
- 散列-分离链接法(数据结构与算法分析-C语言描述)
- 散列表1: 基于分离链接法的散列表
- 哈希表(一)(散列)分离链接法实现
- 散列的冲突解决方法之分离链接法
- hash,分离链接法,探测散列表(二次探测),再散列的代码
- 分离链接法实现散列表
- 分离链接散列表--C语言实现
- 数据结构:散列1(分离链接法)
- 分离链接散列表的删除例程
- 散列 - 分离链接法
- 第5章 散列——分离链接法
- 分离链接散列表头文件C语言
- 数据结构--解决散列冲突,分离链接法
- [未完]散列_分离链接法
- 数据结构与算法之散列(分离链接法)<七>
- 数据结构与算法分析-分离链接散列表的实现
- 散列表分离链接法初始化、插入、删去等操作(c)
- 哈希(散列)的分离链接法