日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

散列之再散列

發布時間:2023/12/3 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 散列之再散列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1)本文描述總結于 數據結構與算法分析, 但源代碼為原創;
0.2)為什么寫這篇博文? 再散列的代碼實現 包括了 解決沖突的方法實現;很有代表性;(本源代碼采用的解決沖突方法是 平方探測法)


【1】問題+解決方法

1.0)開放定址法定義:它是一種不用鏈接解決沖突的方法:如果有沖突發生, 那么就要嘗試選擇另外的單元,知道找出空的單元為止;

1.1)出現的問題:對于使用平方探測的開放定址散列法,如果表的元素填的太滿, 那么操作的運行時間將開始消耗過長,且 insert 操作可能失敗, 這可能發生在有 太多的移動和插入混合的場合;
1.2)解決方法:建立另外一個大約兩倍大的表(使用一個相關的新散列函數),掃描整個原始散列表,計算每個元素的新散列值并將其插入到新表中;
1.3)看個荔枝:

  • 1)將元素13, 15, 24 和 6 插入到大小為 7 的開放定址散列表中:散列函數是 h(X) = X mod 7;設使用線性探測方法解決沖突問題, 插入結果得到的散列表表示在下圖中:
  • 2)如果將 23 插入表中, 那么從下圖可以看到, 插入后的表將有超過70% 的單元是滿的,因為表填得過滿, 所以我們建立一個新表;該表的大小為 17, 因為17是原表大小兩倍后的第一個素數;新的散列函數為 h(X) = X mod 17;掃描原來的表, 并將元素 6, 15, 23 , 24 以及13 插入到新表中, 如下下圖所示:


【2】再散列

2.1)定義:以上整個操作就叫做再散列;顯然這是一種非常昂貴的操作, 其運行時間為 O(N),因為有N 個元素要再散列而表的大小約為2N, 不過由于不是經常發生,所以實際效果根本不是那么差;
2.2)再散列的實現:
再散列可以用平方探測以多種方法實現:

  • 1)一種做法是:只要表滿到一半就再散列;
  • 2)另一個極端方法是:只有當插入失敗時才再散列;
  • 3)第3種方法即途中策略:當表到達某一個裝填因子時進行再散列。由于隨著裝填因子的增加,表的性能有所下降, 因此,以好的截止手段實現的第三種策略, 可能是最好的策略;

2.3)再散列的作用:
再散列就是把 程序員從表大小的擔心中解放出來, 這一點很重要, 因為在復雜的程序中散列表不能夠做得任意地大;


【3】源代碼+打印結果

3.1)解決沖突的方法:我們采用的是平方探測,1,-1,4,-4,……
3.2)Attention)在 “再散列”的代碼中,我們為 HashTable 添加另一個 capacity 成員,用于和 size 相除構成 裝填因子,以便于判斷該裝填因子是否超出某個值;
3.3)downlaod source code : https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter5/p123_rehash.c
3.4)source code at a glance :

#include <stdio.h> #include <malloc.h> #include <math.h>#define ElementType int #define Error(str) printf("\n error: %s \n",str) struct HashTable; typedef struct HashTable *HashTable; struct HashEntry; typedef struct HashEntry *HashEntry; typedef HashEntry EntryArray;HashTable initHashTable(int size); int find(ElementType key, HashTable ht); HashTable insert(ElementType key, HashTable ht);enum EntryType {Legitimate, Empty, Deleted};struct HashEntry {ElementType key;enum EntryType status; };struct HashTable {EntryArray entryArray;int capacity;int size; };//judge whether the value is prime or not, also 1 or 0 int isPrime(int value) {int temp;int flag;flag = 1;temp = 2;while(temp < sqrt(value)){if(value % temp == 0)flag = 0;temp++;}return flag; }// compute the minial prime greater than the value int nextPrime(int value) { value++;while(1){if(isPrime(value))break;value++;}return value; } // hash function int hashFunc(int key, int capacity) {return key % capacity; }// the rehash function to expand hash table capacity upto twice capcity HashTable rehashFunc(HashTable ht) {int capacity;int oldCapacity;int i;EntryArray temp;temp = ht->entryArray;oldCapacity = ht->capacity;capacity = nextPrime(ht->capacity * 2);ht = initHashTable(capacity);for(i = 0; i < oldCapacity; i++)if(temp[i].status == Legitimate)insert(temp[i].key, ht);free(temp);return ht; }// initializing HashTable with given size and the table size should be a prime number HashTable initHashTable(int capacity) {HashTable ht; int i;ht = (HashTable)malloc(sizeof(struct HashTable)); // allocate memory for HashTableif(!ht) {Error("out of space, from func initHashTable");return NULL;}ht->capacity = capacity; // the table capacity should be a prime numberht->size = 0; // the number the hash table stores elementht->entryArray = (HashEntry)malloc(capacity * sizeof(struct HashEntry)); // allocate memory for entry arrayfor(i = 0; i < capacity; i++) ht->entryArray[i].status = Empty;return ht; }// insert the entry with value key into the Hash Table HashTable insert(ElementType key, HashTable ht) {int index;double loadFactor = 0.7; // let the load facotr equals to 0.7, of cource load factor depends on your minddouble temp;index = find(key, ht);if(ht->entryArray[index].status != Legitimate){ht->entryArray[index].status = Legitimate;ht->entryArray[index].key = key;ht->size++;// judge whether the load facotr is greater than the certain valuetemp = (double) ht->size / ht->capacity; if(temp >= loadFactor)ht = rehashFunc(ht);}return ht; }// find the index the entry with key should be placed into int find(ElementType key, HashTable ht) // find the hash entry with value key {int index; int collisionIndex; int minus = -1;int temp;collisionIndex = 0;index = hashFunc(key, ht->capacity); // call the first hash function for allocating empty position for storing the key temp = index;while(ht->entryArray[temp].status != Empty && ht->entryArray[temp].key != key ) // adopting square probing{if(minus == -1)collisionIndex++;minus *= -1;temp = collisionIndex * collisionIndex * minus; temp = (index + temp) % ht->capacity;} return temp; }void printHashTable(HashTable ht) {ElementType key;int i; if(!ht)Error("printing execution failure, for hashtable is null, from func printHashTable"); i = 0;while(i < ht->capacity) {printf("\n\t index[%d] = ", i);key = ht->entryArray[i].key; if(ht->entryArray[i].status == Legitimate)printf("%d", key); elseprintf("NULL");printf(" "); i++;}printf("\n\n"); }int main() {HashTable ht = NULL;int dataSize = 4;int i;ElementType key[] = {13, 15, 24, 6};printf("\n\t=== test for rehashing the hash table with load factor 0.7 and capacity 7, and adopting square probing ===\n");ht = initHashTable(7);// the size of HashTable must be prime number;printf("\n\t=== test for inserting 13, 15, 24, 6 in turn into the hash table ===\n");for(i = 0; i< dataSize; i++) ht = insert(key[i], ht); printHashTable(ht); printf("\n\t=== test for inserting 23 into the hash table ===\n");ht = insert(23, ht); printHashTable(ht); printf("\n\t=== test for inserting 40 into the hash table ===\n");ht = insert(40, ht); printHashTable(ht); return 0; }

3.5)printing result

總結

以上是生活随笔為你收集整理的散列之再散列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。