散列表

散列表的思想就是把关键值送给一个散列函数,产生出一个散列值,这个值平均分布在一个整数区域中

 

=>散列表的实现的细节

1 当数组足够大时可以直接寻址不需要散列函数,常数操作时间O(1)

   但数据规模远大于散列表大小时,考虑到空间的局限性,需要散列函数使关键值均匀的分开

2 散列表的装载因子,也就是实际决定散列表运算时间的参数, 数据规模n 除与  散列表数组大小mα = n/m

3 散列函数核心是采取一些措施尽可能地使关键字均地分开

   确保关键字的独立性 => 构造一个良好的散列函数

4 当关键值均匀地存储在散列链表里,花费常数操作时间+链表长度(数据规模n 除与 散列表数组大小m )=  O(1)+n/m

    如果散列函数弱爆了,几乎所有值都在一个链表里,那么花费线性时间(根据数据规模n)O(n)

5 散列表的大小为1001(选取素数,有助于更加均匀的分开关键值)

6 散列函数通过一系列相乘相加(基数为31),获取散列值(获取方式请看代码),最终值根据数组大小求模返回

7 通过链表解决碰撞(散列值相同情况),即散列表相当于一个数组,每个元素有一个链表

8 通过键 获取值的 一种散列表(键值对,使用动态分配内存)

  1 #include <iostream>
  2 #include <crtdbg.h>
  3 using namespace std;
  4 
  5 typedef int DataType;
  6 
  7 struct Node
  8 {
  9     DataType data;
 10     char *str;
 11     Node * next;
 12 };
 13 //可以直接使用一个结构体Node实现
 14 //之所以分开是为了增加灵活性
 15 struct hashNode
 16 {
 17     Node *node;
 18     //hashNode *next;
 19 };
 20 
 21 class Hash
 22 {
 23 private:
 24     enum 
 25     {
 26         MULTIPLIER = 31,  //乘法散列基数(根据书里的经验 37 也可)
 27         SIZE = 1001   //使用素数确定散列表大小,尽可能把关键吗均匀地分开
 28     };
 29     hashNode *hashTable[SIZE];//散列表
 30     int hashFn(const char* key);//散列函数
 31 public:
 32     Hash()
 33     {
 34         Init();
 35     }
 36     ~Hash()
 37     {
 38         Delete();
 39     }
 40     void Init();
 41     void Delete();
 42     bool Insert(const char* key, const DataType &data);
 43     bool ExtractData(const char* key);//通过键删除该值
 44     bool Find(const char* key, DataType &outData);
 45     void Print()const;
 46 
 47 };
 48 int Hash::hashFn(const char* key)
 49 {
 50     int hashVal = 0;
 51     for (const char *p = key; *p != '\0'; ++p)
 52     {
 53         hashVal = MULTIPLIER*hashVal+ *p;
 54     }
 55     return hashVal%SIZE;
 56 }
 57 void Hash::Init()
 58 {
 59     for (int i=0; i<SIZE; ++i )
 60     {
 61         hashTable[i] = NULL;  
 62     }
 63 }
 64 //释放内存 str、碰撞的node以及hashTable表头
 65 void Hash::Delete()
 66 {
 67     for (int i=0; i<SIZE; ++i)
 68     {
 69         if (hashTable[i] !=NULL)
 70         {
 71             for (Node *p = hashTable[i]->node; p != NULL;)
 72             {
 73                 Node *pTemp = p->next;
 74                 delete [] p->str;  
 75                 delete p;
 76                 p = pTemp;
 77             }
 78             hashTable[i]->node = NULL;
 79             delete hashTable[i];
 80             hashTable[i] = NULL;
 81         }
 82     }
 83 }
 84 //添加元素
 85 bool Hash::Insert(const char* key, const DataType &data)
 86 {
 87     int index = hashFn(key);
 88     if (hashTable[index] == NULL)
 89     {
 90         hashTable[index] = new hashNode;
 91         hashTable[index]->node = new Node;
 92         hashTable[index]->node->data = data;
 93         hashTable[index]->node->str = new char[sizeof(key)+1];
 94         strcpy(hashTable[index]->node->str, key);
 95         hashTable[index]->node->next = NULL;
 96     }
 97     else
 98     {
 99         Node* p = new Node;
100         p->data = data;
101         p->str = new char[sizeof(key)+1];
102         strcpy(p->str, key);
103         p->next = hashTable[index]->node->next;
104         hashTable[index]->node->next = p;
105     }
106     return true;
107 }
108 //删除元素
109 bool Hash::ExtractData(const char* key)
110 {
111     int index = hashFn(key);
112     if (hashTable[index] == NULL)
113     {
114         return false;
115     }
116     else
117     {  //考虑两种情况,hashTable表头 与 链表
118         if (strcmp(hashTable[index]->node->str, key) == 0)
119         {
120             Node *p = hashTable[index]->node->next;
121             Node *pTemp = hashTable[index]->node;
122             delete [] pTemp->str;
123             delete pTemp;
124             hashTable[index]->node = p;
125 
126             return true;
127         }
128         else
129         {
130             Node *pPreNode = hashTable[index]->node;
131             for (Node *p=pPreNode->next; p !=NULL; )
132             {    
133                 if (strcmp(p->str, key) == 0)
134                 {
135                      pPreNode->next = p->next;
136                      delete [] p->str;
137                      delete p;
138                      p = NULL;
139 
140                      return true;
141                 }
142                 pPreNode = p;
143                 p=p->next;
144             }
145         }
146         return false;
147     }
148 }
149 //通过键查找值,如果找到通过outData返回
150 bool Hash::Find(const char* key, DataType &outData)
151 {
152     int index = hashFn(key);
153     if (hashTable[index] == NULL)
154     {
155         return false;
156     }
157     else
158     {
159         for(Node *p = hashTable[index]->node;p !=NULL; p = p->next )
160         {
161             if (strcmp(p->str, key) == 0)
162             {
163                 outData = p->data;
164                 return true;
165             }
166         }
167     }
168     return false;
169 }
170 void Hash::Print()const
171 {
172     for (int i=0; i<SIZE; ++i)
173     {
174         if (hashTable[i] != NULL)
175         {
176             for (Node *p = hashTable[i]->node; p!=NULL; p = p->next)
177             {
178                 cout << p->str << "\t" << p->data << endl;
179             }
180         }
181     }
182 }
183 void main()
184 {
185     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
186 
187     Hash hash;
188     hash.Insert("tom", 15);
189     hash.Insert("bart", 17);
190     hash.Insert("shan", 17);
191     hash.Insert("eve", 16);
192     hash.Insert("jack", 21);
193     hash.Print();
194     hash.ExtractData("jack");
195     cout << endl;
196     hash.Print();
197 
198     cout << endl;
199     DataType data=0;
200     if (hash.Find("shan",data))
201     {
202         cout << "shan:   " << data << endl; 
203     }
204 
205     system("pause");
206 }

 

 

 

posted on 2014-04-24 02:26  Seven++  阅读(287)  评论(0编辑  收藏  举报

导航