散列数据结构C++描述

来源:互联网 发布:地理数据名词解释 编辑:程序博客网 时间:2024/05/15 17:42

本文进行两种散列的实现——线性开型寻址散列,链表散列

散列表——一种动态集合结构,它仅支持Insert,Search和Delete操作

基本规则:关键字key,index=fun(key),T[index]卫星数据,函数fun即散列函数。
查找一个元素的期望时间为O(1)

直接寻址表:关键字全域比较小,使用数组完全存储,一一对应。Insert,Search和Delete操作都是O(1)
散列表:关键字全域较大,可能出现碰撞。
解决碰撞之方法:
1)找到合适的散列函数。精心选择散列函数,并且仍然要解决可能出现的碰撞,该方法不太彻底。
2)链接法(实现)
给定一个能存放n个元素、具有m个槽位的散列表T,定义T的装载因子a=n/m,即一个链中平均存储的元素数。
任何元素散列到m个槽中每一个的可能性是相同的,且与其他元素已被散列到什么位置上是独立无关的。
这称为简单一致散列。一次成功查找为O(1+a),a=n/m,插入删除O(1),注a(书中为阿尔法)
3)开放寻址方法(例如线性开行寻址散列)
所有的元素都存放在散列表中,没有链表(即没有元素存放在散列表外),装载因子不大于1。
插入一个元素是,可以连续的检查散列表的各项,直到找到一个空槽来放置待插入的关键字时为止。


设计散列函数(算法设计略)
启发式方法:乘法散列和除法散列
随机化方法:全域散列

线性开型寻址散列实现
对散列表元素的删除操作执行起来比较困难;但可以解决,方法是:
删除槽i时,在将槽i的中设置一个特定的值DELETED,而不用NIL。当然相应的Hash-Search和Hash-Insert都要配合修改。
这样查找时间不依赖于装载因子a了。因此,在必须删除关键字的应用中,往往采用链接法来解决碰撞。

以下实现的删除方法,是在下信手胡写,并不正确。
// file hash.h#ifndef HashTable_#define HashTable_#include <iostream>#include <stdlib.h>#include "xcept.h"using namespace std;template<class E, class K>class HashTable{   public:      HashTable(int divisor = 11);      ~HashTable() {delete [] ht; delete [] empty;}      bool Search(const K& k, E& e) const;      HashTable<E,K>& Insert(const E& e);      HashTable<E,K>& Delete(E& e);      void Output();// output the hash table   private:      int hSearch(const K& k) const;      int D; // hash function divisor      E *ht; // hash table array      bool *empty; // 1D array};template<class E, class K>HashTable<E,K>::HashTable(int divisor){// Constructor.   D = divisor;   // allocate hash table arrays   ht = new E [D];   empty = new bool [D];   // set all buckets to empty   for (int i = 0; i < D; i++)      empty[i] = true;}template<class E, class K>int HashTable<E,K>::hSearch(const K& k) const{// Search an open addressed table. // Return location of k if present. // Otherwise return insert point if there is space.   int i = k % D; // home bucket   int j = i;     // start at home bucket   do {      if (empty[j] || ht[j] == k) return j;      j = (j + 1) % D;  // next bucket      } while (j != i); // returned to home?   return j;  // table full}template<class E, class K>bool HashTable<E,K>::Search(const K& k, E& e) const{// Put element that matches k in e. // Return false if no match.   int b = hSearch(k);   if (empty[b] || ht[b] != k) return false;   e = ht[b];   return true;}template<class E, class K>HashTable<E,K>& HashTable<E,K>::Insert(const E& e){// Hash table insert.   K k = e; // extract key   int b = hSearch(k);   // check if insert is to be done   if (empty[b]) {empty[b] = false;                  ht[b] = e;                  return *this;}   // no insert, check if duplicate or full   if (ht[b] == k) throw BadInput(); // duplicate   throw NoMem(); // table full}template<class E, class K>HashTable<E,K>& HashTable<E,K>::Delete(E& e){// Hash table insert.   K k = e; // extract key   int b = hSearch(k);   // check if insert is to be done   if (empty[b])   {       cout << "没有该元素。" << endl;       return *this;   }   empty[b] = true;   int count = 0;   int index = b+1;   while (index != b)   {       if (index >= D)           index -= D;       K key;       if (!empty[index])       {           key = ht[index];           if ((key % D) != index)               count++;       }       index++;   }   cout << "count=" << count << endl;   E *temp = new E[count];   index = b+1;   int i = 0;   while (index != b)   {       if (index >= D)           index -= D;       K key;       if (!empty[index] && i < count)       {           key = ht[index];           if ((key % D) != index)           {               temp[i] = ht[index];               empty[index] = true;               i++;           }       }       index++;   }   for (i = 0;i < count;i++)       Insert(temp[i]);   delete[] temp;   return *this;}template<class E, class K>void HashTable<E,K>::Output(){   for (int i = 0; i< D; i++) {      if (empty[i]) cout << "empty" << endl;      else cout << ht[i] << endl;}}#endif
xcept.h文件
// exception classes for various error types#ifndef Xcept_#define Xcept_#include <new>// bad initializersclass BadInitializers {   public:      BadInitializers() {}};// insufficient memoryclass NoMem {   public:      NoMem() {}};// change new to throw NoMem instead of xallocvoid my_new_handler(){   throw NoMem();};//new_handler Old_Handler_ = set_new_handler(my_new_handler);//set_new_handler(my_new_handler);// improper array, find, insert, or delete index// or deletion from empty structureclass OutOfBounds {   public:      OutOfBounds() {}};// use when operands should have matching sizeclass SizeMismatch {   public:      SizeMismatch() {}};// use when zero was expectedclass MustBeZero {   public:      MustBeZero() {}};// use when zero was expectedclass BadInput {   public:      BadInput() {}};#endif
hash.cpp测试实例
// test hash table with linear open addressing#include <iostream>#include "hash.h"class element {   friend int main(void);   public:      operator long() const {return key;}//   private: g++ has a problem with main a friend      int data;      long key;};int main(void){   HashTable<element, long> h(11);   element e;   e.key = 80;   h.Insert(e);   e.key = 40;   h.Insert(e);   e.key = 65;   h.Insert(e);   h.Output();   e.key = 58;   h.Insert(e);   e.key = 24;   h.Insert(e);   cout << ' ' << endl;   h.Output();   e.key = 2;   h.Insert(e);   e.key = 13;   h.Insert(e);   e.key = 46;   h.Insert(e);   e.key = 16;   h.Insert(e);   e.key = 7;   h.Insert(e);   e.key = 21;   h.Insert(e);   cout << ' ' << endl;   h.Output();   e.key = 99; try {h.Insert(e);}   catch (NoMem)      {cout  << " No memory for 99" << endl;}   cout << "delete 24" << endl;   e.key = 24;   h.Delete(e);   h.Output();   cout << "delete 15,there is not the element" << endl;   e.key = 15;   h.Delete(e);   h.Output();   e.key = 2;   h.Delete(e);   h.Output();   return 0;}             
makefile文件
hash:hash.o hash.o xcept.h        g++ -o hash hash.ohash.o:hash.cpp hash.h xcept.h        g++ -c hash.cpp hash.h xcept.h        g++ -c hash.h        g++ -c xcept.hclean:        rm -f hash *.o *.gch


输出结果:
emptyemptyempty80emptyemptyempty40emptyempty65 emptyempty248058emptyempty40emptyempty65 72124805821340461665 No memory for 99delete 24count=721empty2805813464016765delete 15,there is not the element没有该元素。21empty2805813464016765count=621empty1380584616407empty65



链接法实现














原创粉丝点击