当前位置: 首页 > news >正文

wordpress qux主题沙洋县seo优化排名价格

wordpress qux主题,沙洋县seo优化排名价格,江西求做网站,自己制作app需要什么目录 链地址法Separate Chaining——哈希桶的模拟实现 超大重点分析#xff1a; 两种方法对比 由于在上次的哈希表的底层实现(1)---C版已经详细的阐述了相关的结构和原理#xff0c;哈希表的实现方法主要分为链地址法和开放定址法。开放定址法上次已经实现过了#xff0c…目录 链地址法Separate Chaining——哈希桶的模拟实现 超大重点分析 两种方法对比 由于在上次的哈希表的底层实现(1)---C版已经详细的阐述了相关的结构和原理哈希表的实现方法主要分为链地址法和开放定址法。开放定址法上次已经实现过了这次我们实现一下链地址法。 链地址法Separate Chaining——哈希桶的模拟实现 哈希桶的结构和链表是完全一样的我们这边选择在每个vector里面装入单链表就可以了比较简单嘛所以每个结点和成员都是指针。 #includeiostream #includevector using namespace std; templateclass K struct Hashfunc//仿函数 {     int operator()(const K key)     {         return (int)key;     } }; struct Hashfuncstring//结构体名字必须一致才省略模板 {     int operator()(const string key)     {         int hashi 0;         for (auto e : key)         {             hashi hashi * 31;             hashi hashi e;         }         return hashi;     } }; templateclass K, class V struct Hashnode {     pairK, V _kv;     HashnodeK, V* _next;     Hashnode(const pairK, V kv)         :_kv(kv)         ,_next(nullptr)     {} }; templateclass K, class V, class hash HashfuncK class Hashtable {     typedef HashnodeK, V node; public:     Hashtable()     {         _tables.resize(10, nullptr);//先初始化存有10个空指针的数组     }     ~Hashtable()//需要自己写析构函数的     {         for (int i 0; i _tables.size(); i)         {             node* cur _tables[i];             while (cur)             {                 node* next cur-_next;                 delete cur;                 cur next;             }             _tables[i] nullptr; }     } bool Insert(const pairK, V kv)     {         hash ha;         // 负载因子1扩容         if (n _tables[size])         {             /*HashtableK, V newHT;             newHT._tables.resize(_tables.size() * 2);             for (size_t i 0; i _tables.size(); i)             {                 node* cur _tables[i];                 while(cur)                 {                     newHT.Insert(cur-_kv);//用以前复用的逻辑有点浪费空间了                     cur cur-_next;                 }             }*/             vectornode*newht.resize(_tables.size() * 2, nullptr);             for (int i 0; i _tables.size(); i)             {                 node* cur _tables[i];                 while (cur)                 {                     node* next cur-_next;                     // 旧表中节点挪动新表重新映射的位置                     size_t hashi ha(cur-_kv.first) % newht.size();                     // 头插到新表当然使用尾插也可以                     cur-_next newht[hashi];//头插的逻辑                     newht[hashi] cur;                     cur next;                 }                 _tables[i] nullptr;//置空了头结点后面的结点也就找不到了其实感觉不置空也没什么问题             }             _tables.swap(newht);//再交换一下         }         size_t hashi ha(kv.first) % _tables.size();         //头插         node* newnode new(kv);//通过kv构造一个新结点需要合适的构造函数         newnode-_next _tables[hashi];         _tables[hashi] newnode;         n;     } Node* Find(const K key)     {         hash he;         size_t hashi he(K) % _tables.size();         node* cur _table[hashi];         while (cur)         {             if (cur-_kv.first key)             {                 return cur;             }             cur cur-_next;         }         return nullptr;     } bool Erase(const K key)     {         hash ha;         if (Find(key) nullptr)         {             return false;         }         else         {             size_t hashi ha(K) % _tables.size();             node* cur _table[hashi];             node* prev nullptr;             while (cur)             {                 if (cur-_kv.first key)                 {                     if (prev nullptr)                     {                         _tables[hashi] cur-_next;                     }                     else                     {                         prev-_next cur-_next;                     }                     delete cur;                     cur nullptr;                     --n;                     return true;                 }                 prev cur;                 cur cur-_next             }         }     } private:     vectornode* _tables;// 使用指针数组     size_t n 0;//负载因子 }; 超大重点分析 为什么需要自己写析构函数呢因为如果让系统调用默认构造的话成员中负载因子属于内置类型编译器不处理然后vector属于自定义类型编译器会调用vector的默认构造这样vector里面的单链表就没有办法析构了就会照成内存泄漏。 为什么扩容不复用insert了呢先说一下为什么会需要扩容随着数据的不断大量的插入单链表肯定在某种情况下会使得某个链表过于长这样在查找哈希表的时候会使得时间复杂度过于大了所以引入负载因子n进行控制当n size时就扩容为什么在扩容时不建议复用呢因为这样不断的创造新的结点而放着旧结点不直接拿来用的话会比较浪费空间创造一个结点的消耗还是比较大的。 为什么这边需要写构造函数因为insert传的是pair那根据这个pair构造新结点的话需要自己写一个构造默认构造用不上。 为什么这边哈希桶状的结构是单链表而不是直接使用list或者C11新加入的forward_list呢首先没说不可以但是用单链表不是更简单吗forward_list尽量少用。 vectorlistpairK, V _tables;  // 指针数组 像上面这种就是使用list的写法但是到时候封装的iterator实现起来会比较困难 struct Bucket//联合体 {        listpairK, V _lt;        mapK, V _m;        size_t _bucketsize;   // 8 map  8 list }; vectorBucket _tables; 但是呢就算是有扩容操作还是会有人故意使用一些很极端的数据使得即使多次扩容还是显得某个链表的插入数据很多导致每个链表插入数据的数目不平衡。所以为了解决这种情况有些人会选择当负载因子过大时转而使用搜索树map来代替list实现存储如上 最后一个问题为什么使用头插呢因为其实无论是头插还是尾插在Find还是erase都没什么显著差别的但是在扩容时头插会比尾插更有优势因为每个结点刚开始初始化时的_next结点都是空 这样当头插到开头时每次指向的都是空这样就不会把多余的结点带出来了如果是尾插就需要最后再手动将_next置空。 两种方法对比 应用链地址法处理溢出需要增设链接指针似乎增加了存储开销。事实上 由于开地址法必须保持大量的空闲空间以确保搜索效率如二次探查法要求装载因子a 而表项所占空间又比指针大的多所以使用链地址法反而比开地址法节省存储空间。
http://www.hkea.cn/news/14356936/

相关文章:

  • 唐山住房和城乡建设局网站专业创建网站
  • 网站系统开发创新的做网站
  • 客户网站留言旅游网站建设背景
  • 廊坊网站快照优化公司网页设计基础教学
  • 网站建设需要什么资料可以做营销任务的网站
  • 怎样做网站备案wordpress 勾子
  • 中国建设银行 英文网站房产信息网的官网链接
  • 制作网站的代码小学生家长网站建设需求
  • 贵州贵州省住房和城乡建设厅网站找人做菠菜网站需要多少钱
  • 网站建设可研建设银行网站显示404
  • 小型企业的网站建设论文建设局局长有实权吗
  • 外卖做的比较好的网站辽宁模板网站建设公司
  • 做网站网站建设教程做网站的大型公司
  • 个人承接网站建设甘肃网络营销是什么
  • 网站开发及服务合同网站设计建设专业服务
  • 谷歌找网站后台让别人做网站的话术
  • 做网站电子版报价模板网页开发者工具怎么用
  • 做一个销售网站需要多少钱做网站是用c 吗
  • 程序员做网站美工能过关吗免费模板建站
  • 丰浩网站建设中心网站建设筹备方案
  • 汽配信息门户网站模板网络推广公司营业执照
  • 金融理财网站建设莲湖微网站建设
  • 儿童网站开发 论文装潢设计装修
  • 肥料网站建设 中企动力平面广告设计要学的软件
  • 做流量网站要做哪一种河北招投标公共服务平台
  • 网站首页布局seo国外校园网站建设
  • 做棋牌开发的网站竞价软件哪个好
  • 网站ip和pv网站怎么添加广告
  • 女朋友在互联网公司做网站国防教育网站建设方案
  • 肇庆高端品牌网站建设wordpress 怎么打开