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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

哈希--直接定值法和除留取余法

發(fā)布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 哈希--直接定值法和除留取余法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. 哈希是一種算法,哈希表是用哈希算法構(gòu)造出來的一種數(shù)據(jù)結(jié)構(gòu) 2. 哈希算方法的幾種方法
  • 直接定值法
這里有一個例題,就是我們想判斷某一字符串中,某一個字符出現(xiàn)的個數(shù),我們可以使用哈希的思想,就是可以遍歷一遍字符串,然后開辟一個擁有26數(shù)據(jù)的整型數(shù)組,然后初始化全部為0,然后統(tǒng)計利用一種映射的思想,遍歷字符串的時候,就把相應(yīng)的位置++,每次我們查找某一個字符的時候,一下子就可以定值到那個字符的位置 還有一個例子就是,比如讓我們存儲1-10這個區(qū)間的不重復(fù)的數(shù)據(jù),這個時候我么也是開辟一個擁有十個元素的整型數(shù)組,然后每個數(shù)據(jù)對應(yīng)給位置,這樣我們在查找的時候,就可以直接查找到這個數(shù)據(jù)是否存在。 第三個例子是,這里有一些 數(shù)據(jù),比如是1001,1006,1009,1007這個時候我們知道數(shù)據(jù)的范圍,我們也是可以開辟一個存儲空間來存放這個數(shù)據(jù),只不過這個時候我們不需要開辟1000多個大小的數(shù)組,我么只需要開辟十個即可,上面的每個數(shù)據(jù)都減去1000,然后在存放在這個位置,然后我們讀取的時候也是按照這個規(guī)則讀取 分析:上面的幾種都是特殊的簡單的情況,太具有局限性,還有就是如果我們的數(shù)據(jù)跨度很大的話,要開辟很大的存儲空間,這顯然是不合適的,但是一種解題的思路
  • 除留取余法
這里有一部分?jǐn)?shù)據(jù)然后我們不能開辟所有的大小的空間,這個時候我呢就出現(xiàn)了一個除留取余法,我們的可以把數(shù)據(jù)都取余數(shù)組的長度,然后放置在相應(yīng)的位置上面去。 致命缺點:哈希沖突,即是我們的數(shù)據(jù)可能映射的位置是同一個位置 法一:閉散列法--開放地址法 (1)第一種方式是線性探測 其他的發(fā)生沖突的數(shù)據(jù)直接往后面走,直到有一個位置上面的數(shù)據(jù)為空,這個時候把數(shù)據(jù)放置上去。 比如我么的數(shù)據(jù),有89,18,49,58,9,我們開辟的整型數(shù)組的空間空間時十個,然后我們放置89,89%10 = 9,然后把89放置在了第九個位置上面去,接著是放置18,18被放置在了8這個位置上面。然后拿到49的時候,我們的數(shù)據(jù)9這個位置已經(jīng)后數(shù)據(jù),這個時候,我們依次往后走,知道扎到了0號位置是空的,于是49被放置在了0這個位置上面去了。同樣 的方法放置其他的數(shù)據(jù)。 數(shù)據(jù)放置好了之后,就是查找數(shù)據(jù)了,這個是時候,如果找9,首先定位到9這個位置上面上,然后沒有找到,然后就是依次往后面找,知道找到9,或者就是找到一個空位置停止,這個時候 是沒有找到相關(guān)的數(shù)據(jù)。 但是這種方式留下了一個問題就是,如果我們沖突的數(shù)據(jù)都是集中在了9這個位置了,那每次查找的時候是不是很麻煩,這個時候我我們采用的方法及時二次探測。 (2)第二種方式是二次探測 二次探測的方式值這樣的,89進(jìn)來的時候還是直接放置數(shù)據(jù),但是當(dāng)49進(jìn)來的時候,不是直接往后面放置了,而是往后移動1的平方個位置,如果是空的就是直接放置,如果不是空的,就是相對于起始位置移動2的 平方個,依次類推下去,直到有一個位置為空。 第一個問題:我們既然已經(jīng)知道了一次探測的沖突比較大,所以我們這里直接采用的是二次探測 第二個問題:我們的考慮使用數(shù)組,但是因為后面的數(shù)據(jù)可能會增加的很大,所以我們還會考慮增容的操作,這個時候我們不妨直接使用vector。 第三個問題:我們一開始的時候,初始化的時候,初始值應(yīng)該是多少呢,大家可能和自然的想到了是0,但是有一個問題就是,但是如果我要找的數(shù)據(jù)就是0的,那不是GG了,所以我們在設(shè)計類的成員變量的時候的時候,vector里面的內(nèi)容 可以放置的是一個結(jié)構(gòu)體,結(jié)構(gòu)體的一部分是數(shù)據(jù),一部分是標(biāo)識位,標(biāo)識我們的這個位置上面有沒有數(shù)據(jù) 第四個問題:我們既然有增加數(shù)據(jù),就一定有刪除數(shù)據(jù),那個如果是上面的例子,我現(xiàn)在刪除了一個數(shù)據(jù)是49,然后我接下來可能是要找9,這個時候首先定位到下標(biāo)為9的這個位置,然后往后面二次探測1的平方,這個時候找到了49這個 位置,發(fā)現(xiàn)是空,就不往下找了,顯然這是不符合 我們的要求的,于是我們想設(shè)計結(jié)構(gòu)體的時候,這個標(biāo)識位有三個值,一個標(biāo)識有數(shù)據(jù),一個標(biāo)識沒有數(shù)據(jù),一個標(biāo)識刪除數(shù)據(jù),于是我們想到了枚舉類型。 第五個問題:我們需要考慮的什么時候增容呢,一開始的想法是當(dāng)vector滿了之后再增容 ,可是這種增容的話,當(dāng)我們的vector滿的 時候是不是數(shù)據(jù)的沖突就可能大呢,于是我們想的是當(dāng)已經(jīng) 放置的數(shù)據(jù)個數(shù)的大小時vector的容量大小的0.7的時候開始增容。 第六個問題:我們的數(shù)據(jù)在放入的時候,可能在二次探測的時候,可能會出現(xiàn)一只循環(huán)在寫某些位置,這個 問題下一講在解決。
代碼:hashtable.h
#include<iostream>
using namespace std;
#include<vector>//作為一個標(biāo)記位
enum State   
{EMPTY,EXIT,DEL
};//哈希節(jié)點
template<class K,class V>
struct HashNode
{pair<K, V> _kv;State _state;HashNode():_state(EMPTY){}
};template<class K,class V>
ostream& operator<<(ostream &out, HashNode<K,V> node)
{out << " "<< " " << node._state;return out;
}template<class K,class V>
class HashTable
{//friend ostream& operator<<(ostream &out, HashNode<K, V> node);
public:HashTable():_n(0){_table.resize(10);  //預(yù)留的數(shù)租空間大小是}//插入函數(shù)bool Insert(const pair<K,V> node){Capacity();int m = HanshFunc(node);  //HanshFunc,找到我需要插入的一個下標(biāo)size_t index = m;size_t i = 0;while (_table[index]._state == EXIT){index = m;i++;index = m + i*i;while (index >= _table.capacity()){index = index - _table.capacity();}}_table[index]._kv = node;_table[index]._state = EXIT;_n++;return true;}int Search(const pair<K, V> node){size_t m = HanshFunc(node);size_t index = m;size_t i = 0;while (_table[index]._kv.first != node.first){if (_table[index]._state == EMPTY){return -1;}index = m;i++;index = m + i*i;while (index >= _table.capacity()){index = index - _table.capacity();}}return index;}private:void Capacity(){//if (_n / _table.capacity() >= 0.7)   //這類需要改進(jìn)的一個地方 就是,我們不能使用0.7,因為除以了之后,不是一個小數(shù)//{//	printf("增容\n");//}if (_n * 10 / _table.capacity() >= 7){printf("增容\n");}}int HanshFunc(const pair<K, V> node){size_t index = node.first % _table.capacity();return index;}private:vector<HashNode<K,V>> _table;  //這個是數(shù)組size_t _n;  //當(dāng)前放置的數(shù)據(jù)的個數(shù)是多少
};


HashTable.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"hashtable.h"int main()
{HashTable<int, int> a;pair<int, int> p(5,6);pair<int, int> p1(15,7);pair<int, int> p2(25, 6);pair<int, int> p3(85, 6);pair<int, int> p4(75, 6);pair<int, int> p5(95, 6);pair<int, int> p6(2, 6);pair<int, int> p7(4, 6);a.Insert(p);a.Insert(p1);a.Insert(p2);a.Insert(p3);a.Insert(p4);a.Insert(p5);a.Insert(p6);a.Insert(p7);cout << a.Search(p);return 0;
}


總結(jié)

以上是生活随笔為你收集整理的哈希--直接定值法和除留取余法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。