
题目
解决代码及点评
/* hash表,是用hash算法将任意长度的二进制值,映射为较短的固定范围的二进制值 在这个例子里,我们简单的使用 %10作为我们的hash算法。 对10取模会导致经常的冲突,比如13和23,对10取模之后都是3,这种情况下叫做hash算法的冲突 为了解决冲突,需要在一个hash节点上使用链表数据结构来保存冲突的多个数据。 */ #include <iostream> #include <algorithm> #include <vector> #include <memory.h> using namespace std; /* hash表节点 由value和next指针构成 index只是用来打印,无实际意义 */ template<class T> class Node { public: T value; // hash节点值 Node<T> *pNext; // 冲突的下一个节点 int index; // 只是打印 protected: private: }; template<class T> class Hash { public: Hash(); // 构造函数 ~Hash(); // 析构函数 bool insert(T value); // 往hash表中插入数据 bool deleteNode(T value); // 删除节点 Node<T> *FindValue(T value); // 在hash表中搜索节点 //Node<T> **Top10(); void Print(); // 输出哈希表 protected: private: Node<T> *HashArray[10]; // 定义10个hash节点指针,构成hash简答的hash数据结构 }; // 构造函数:为数据结构申请内存 template<class T> Hash<T>::Hash() { HashArray[10]=new Node<T>[10]; memset(HashArray, NULL, sizeof(Hash)); } // 析构函数,释放内存 template<class T> Hash<T>::~Hash() { delete []HashArray; } // 打印hash表,只是遍历hash数组,输出每个节点的value和index template<class T> void Hash<T>::Print() { Node<T> *node; for(int i=0;i<10;i++) { if (HashArray[i]==NULL) { continue; } node = HashArray[i]; while(node!=NULL) { cout<<node->value<<":"<<node->index<<" "; node=node->pNext; } cout<<endl; } } /* FindValue:首先通过value%10获得hash的index 然后在指定的index上的链表中搜索节点 */ template<class T> Node<T> *Hash<T>::FindValue(T value) { Node<T> *node; /* 先判断HashArray,如果是空,则不用搜索了 */ if (HashArray==NULL) { return NULL; } /* 根据hash算法,这里我们简单对10取模,获取hash下标 */ node = HashArray[value%10]; if (node==NULL) { return NULL; } /* 在对应坐标的冲突链表中搜索value */ while(node) { if (node->value==value) { return node; } node=node->pNext; } return NULL; } /* 插入数据 */ template<class T> bool Hash<T>::insert(T value) { Node<T> *node; /* 首先判断HashArray,如果为空,则无法插入了 */ if (HashArray==NULL) { return false; } /* 根据hash算法获得hash index,并判断index是不是为空, 如果为空,说明该index下还从来未有数据插入过, 那么直接将该输入插入即可 */ if (HashArray[value%10]==NULL) //判断头数组中有没有 { /* 构造节点 */ node = new Node<T>; node->value = value; node->index = 1; node->pNext = NULL; /* 直接插入即可,即赋值 */ HashArray[value%10]=node; return true; } /* 如果该index下不为空,那么说明冲突,也有可能该值以前就已经插入过,通过findvalue去查找下 如果能找到说明该值已经在hash表中,index++表明该值被多次插入过 */ if (FindValue(value)!=NULL) { FindValue(value)->index++; return false; } /* 如果findValue失败,说明数据没有插入过,那么构造节点 */ node = new Node<T>; //头插法 node->value = value; node->index = 1; /* 以下两句代码将新节点加入到冲突链表的头 比如有一个冲突节点如下: -> 13 -> 23 -> NULL 这时候加入了33,那么33的位置应该在 -> 33 -> 13 -> 23 -> NULL */ node->pNext = HashArray[value%10]; HashArray[value%10]=node; return true; } /* 删除节点 */ template<class T> bool Hash<T>::deleteNode(T value) { Node<T> *node; if (HashArray==NULL) { return false; } // 根据hash算法获取头数组,如果头数组没有,则表明该value不存在 if (HashArray[value%10]==NULL) //判断头数组中有没有 { return false; } /* 通过FindValue去搜索,看节点是否存在,如果不存在也不用删除了 */ if (FindValue(value)!=NULL) { /* 如果存在,那么通过hash算法,获取冲突链表头 */ node = HashArray[value%10]; /* 如果链表头节点就是该value,则删除头节点 */ if (node->value==value) { Node<T> *temp = node; node = node->pNext; HashArray[value%10] = node; delete temp; return true; } /* 如果不是在冲突链表头,那么就在冲突链表中,循环的查找吧 */ while(node->pNext!=NULL) { // 当找到这个value时 if (node->pNext->value==value) { // 将这个value对应的node在链表里删除 Node<T> *temp = node->pNext; node->pNext=temp->pNext; delete temp; return true; } node=node->pNext; } return false; } return false; } /* 测试主函数 */ int main() { Hash<int> h; h.insert(4); h.insert(34); h.insert(54); h.insert(35); h.insert(8); h.insert(22); h.insert(48); h.insert(9); h.insert(32); h.insert(2); h.insert(3); h.insert(54); h.insert(37); h.insert(8); h.insert(54); h.insert(6); h.insert(9); h.insert(12); h.insert(12); h.insert(23); h.insert(37); h.insert(48); h.insert(54); h.insert(66); h.insert(9); h.insert(12); h.Print(); system("pause"); return 0; }
代码下载及其运行
代码下载地址:http://download.csdn.net/detail/yincheng01/6704519
解压密码:c.itcast.cn
下载代码并解压后,用VC2013打开interview.sln,并设置对应的启动项目后,点击运行即可,具体步骤如下:
1)设置启动项目:右键点击解决方案,在弹出菜单中选择“设置启动项目”
2)在下拉框中选择相应项目,项目名和博客编号一致
3)点击“本地Windows调试器”运行
程序运行结果