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

建立网站目录结构应遵循的方法和建议seo怎么优化步骤

建立网站目录结构应遵循的方法和建议,seo怎么优化步骤,任县网站制作,广东省农业农村厅官网1.前期准备与框架搭建 第一步:将哈希表(链地址法)的头文件加进项目,然后创建两个头文件Unordered_Map和Unorderd_Set。 第二步:unordered_set框架与unordered_map框架搭建 unordered_set: #pragma once #include"…

1.前期准备与框架搭建

第一步:将哈希表(链地址法)的头文件加进项目,然后创建两个头文件Unordered_Map和Unorderd_Set。

第二步:unordered_set框架与unordered_map框架搭建

unordered_set:

#pragma once
#include"hashtable.h"
namespace myself
{template<class K, class V>class unordered_map{public:private:HashTable<K, pair<K, V>> _ht;};
}

unordered_map:

#pragma once
#include"hashtable.h"
namespace myself
{template<class K>class unordered_set{public:private:HashTable<K, K> _ht;};
}

这里我们传给哈希表的参数不再是key和value,而是单独的k和容器存储的数据类型(set中是key,map中是pair<K,V>),这样可以兼容set和map进哈希表

1.1支持insert

(1)解决find和erase中需要key查找,而哈希表中不确定存储数据类型是key还是key_value的问题

解法:使用仿函数KeyOfT,仿函数作用是返回容器的key值引用

首先我们要在unordered_set中写一个SetOfT,返回值类型为K,不过需要注意的是返回的是const类型的,否则会导致权限放大

struct SetOfT{const K& operator()(const K& key){return key;}};

然后是unordered_map

	struct MapOfT{const K& operator()(const pair<K,V>& data){return data.first;}};

然后在哈希表中加一个模板参数KeyOfT,用于接收unordered_set和unordered_map的仿函数

(2)将key类型转换为可以进行取模运算的类型

解法:使用仿函数Func,对于特殊类型如string就进行类模板特化

template<class K>
struct HashFunc
{size_t operator()(const K& key){return (size_t)key;}
};

使用struct是因为这个仿函数是需要哈希表可以直接调用的,所以用struct就可以默认开放给类外面

(3)更改哈希表中的insert

bool Insert(const T& data){KeyOfT kot;Func fc;//不允许冗余if (Find(kot(data))) return false;//负载因子为1就扩容if (_n == _tables.size()){vector<Node*> newtable (2 * _tables.size());for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){//将旧的表中节点挪到新表中Node* next = cur->_next;size_t hash0 = fc(kot(cur->_data)) % newtable.size();//头插cur->_next = newtable[hash0];newtable[hash0] = cur;//更新curcur = next;}_tables[i] = nullptr;}newtable.swap(_tables);}//头插size_t hash0 = fc(kot(data)) % _tables.size();Node* newnode = new Node(data);newnode->_next = _tables[hash0];_tables[hash0] = newnode;_n++;return true;}

1.只有需要使用key的情况我们才用kot将key取出来,如果就是要使用容器存储的数据类型,比如节点构造,那么我们就需要直接用data

2.func主要用于进行取模运算的时候,此时需要key是一个可以取模运算的数据类型

(4)更改Find与Erase

	Node* Find(const K& key){Func fc;KeyOfT  kot;size_t hash0 = fc(key) % _tables.size();Node* cur = _tables[hash0];while (cur){if (kot(cur->_data) == key) return cur;cur = cur->_next;}return nullptr;}bool Erase(const K& key){KeyOfT kot;Func fc;size_t hash0 = fc(key) % _tables.size();Node* cur = _tables[hash0];Node* prv = nullptr;while (cur){if (kot(cur->_data) == key)//delete{if (prv == nullptr){_tables[hash0] = cur->_next;}else{prv->_next = cur->_next;}delete cur;--_n;return true;}prv = cur;cur = cur->_next;}return false;}

(5)实现析构

~HashTable(){for (size_t i = 0; i < _tables.size(); i++){
//逐个桶进行释放Node* cur = _tables[i];while (cur){Node* next = cur->_next;delete cur;cur = next;}_tables[i] = nullptr;}}

1.2支持iterator

 //哈希表前置声明template<class K, class T, class KeyOfT, class Func >class HashTable;//迭代器实现template<class K, class T, class KeyOfT, class Func >struct HTIterator{typedef HashTable<K, T, KeyOfT, Func> HT;typedef HashNode<T> Node;typedef HTIterator<K, T, KeyOfT, Func> self;//迭代器存储内容HT* _ht;Node* _node;//构造HTIterator(Node* node,HT* ht):_ht(ht),_node(node){}//运算符重载T* operator->(){return &(_node->_data);}T& operator*(){return _node->_data;}self& operator++(){Func fc;KeyOfT kot;//当前桶没走完Node* cur = _node;if (cur->_next){_node = _node->_next; }else//当前桶走完了,寻找下一个桶的头结点{size_t hashi = fc(kot(_node->_data)) % _ht->_tables.size();hashi++;while (hashi < _ht->_tables.size())//没有走完哈希表{if (_ht->_tables[hashi]){_node = _ht->_tables[hashi];break;}hashi++;}if (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;}bool operator!=(const self& s){return _node != s._node;}bool operator ==(const self& s){return _node == s._node;}};

1.模板参数的缺省参数只能给一次,不能在多个地方重复给,这样会可能导致缺省参数混乱,所以在语法层面禁止了

2.需要在迭代器前面前置声明一下HashTable,告诉编译器他是一个类

3.迭代器++的逻辑:

(1)当前桶没有走完,那么就直接让迭代器指向下一个node,然后返回迭代器

(2)当前桶走完了,需要寻找下一个有数据的桶,若找到了就指向新桶的第一个数据,没有找到就指向nullptr。

最后返回迭代器本身

4.由于迭代器++的逻辑中使用了哈希表的private成员变量,所以我们需要让迭代器成为哈希表的友元函数


接下来我们实现哈希表中的迭代器

//实现begin和endIterator Begin(){//找第一个节点for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return Iterator(_tables[i], this);}}return End();}Iterator End(){return Iterator(nullptr,this);}

begin:寻找哈希表中第一个节点,然后用该节点地址和哈希表本身地址构造迭代器

end:我们以nullptr表示没有节点了,所以用nullptr和哈希表本身地址构造迭代器

然后我们对unordered_set和unordered_map进行封装迭代器

注意要写在public修饰符内部

unordered_set:

		typedef typename HashTable<K, K, SetOfT>::Iterator iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}

unordered_map:

typedef typename HashTable<K, pair<K, V>, MapOfT>::Iterator iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}

1.3支持const_iterator

 支持const迭代器我们只需要在迭代器的模板参数中增加两个参数,Ref和Ptr即可,因为增加他们就可以控制运算符->和*的返回值类型

 //迭代器实现template<class K, class T, class Ref, class Ptr,class KeyOfT, class Func >struct HTIterator{typedef HashTable<K, T, KeyOfT, Func> HT;typedef HashNode<T> Node;typedef HTIterator<K, T,Ref,Ptr,KeyOfT, Func> self;//迭代器存储内容const HT* _ht;Node* _node;//构造HTIterator(Node* node,const HT* ht):_ht(ht),_node(node){}//运算符重载Ptr operator->(){return &(_node->_data);}Ref operator*(){return _node->_data;}self& operator++(){Func fc;KeyOfT kot;//当前桶没走完Node* cur = _node;if (cur->_next){_node = _node->_next; }else//当前桶走完了,寻找下一个桶的头结点{size_t hashi = fc(kot(_node->_data)) % _ht->_tables.size();hashi++;while (hashi < _ht->_tables.size())//没有走完哈希表{if (_ht->_tables[hashi]){_node = _ht->_tables[hashi];break;}hashi++;}if (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;}bool operator!=(const self& s){return _node != s._node;}bool operator ==(const self& s){return _node == s._node;}};

注意:这里我们修改了构造函数的参数,将HT*变为const属性,这是因为后续支持cosnt_iterator的时候会传递的对象是const属性,如果这里参数不是const属性会导致权限被放大。且这里我们即使加上了const也不会影响迭代器逻辑,因为迭代器中没有修改哈希表的部分

然后我们通过控制模板参数重命名一个const迭代器,并对unordered_set和unordered_map套上const迭代器

(1)在HashTable加上const迭代器

template<class K, class T, class KeyOfT,class Func = HashFunc<K>>
class HashTable
{//友元声明template<class K, class T,class Ref,class Ptr ,class KeyOfT, class Func >friend struct HTIterator;typedef HashNode<T> Node;
public:typedef HTIterator<K, T,T&,T*,KeyOfT, Func> Iterator;typedef HTIterator<K, T, const T&, const T*, KeyOfT, Func> Const_Iterator;HashTable(size_t size = 53):_tables(size, nullptr),_n(0){}//实现begin和endIterator Begin(){//找第一个节点for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return Iterator(_tables[i], this);}}return End();}Iterator End(){return Iterator(nullptr,this);}//实现const的begin和endConst_Iterator Begin() const{//找第一个节点for (size_t i = 0; i < _tables.size(); i++){if (_tables[i]){return Const_Iterator(_tables[i], this);}}return End();}Const_Iterator End() const{return Const_Iterator(nullptr, this);}bool Insert(const T& data){KeyOfT kot;Func fc;//不允许冗余if (Find(kot(data))) return false;//负载因子为1就扩容if (_n == _tables.size()){vector<Node*> newtable (2 * _tables.size());for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){//将旧的表中节点挪到新表中Node* next = cur->_next;size_t hash0 = fc(kot(cur->_data)) % newtable.size();//头插cur->_next = newtable[hash0];newtable[hash0] = cur;//更新curcur = next;}_tables[i] = nullptr;}newtable.swap(_tables);}//头插size_t hash0 = fc(kot(data)) % _tables.size();Node* newnode = new Node(data);newnode->_next = _tables[hash0];_tables[hash0] = newnode;_n++;return true;}

(2)给unordered_set和unordered_map加上const迭代器

unordered_map:

typedef typename HashTable<K, pair<K, V>, MapOfT>::Iterator iterator;typedef typename HashTable<K, pair<K, V>, MapOfT>::Const_Iterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}

unordered_set:

typedef typename HashTable<K, K, SetOfT>::Iterator iterator;typedef typename HashTable<K, K, SetOfT>::Const_Iterator const_iterator;const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}

 

1.4将key现在可以修改的情况改为不可修改

 只需要在unordered_set和unordered_map中把容器存储类型中的key变为const属性即可

在private部分,typedef部分修改

typedef typename HashTable<K, const K, SetOfT>::Iterator iterator;typedef typename HashTable<K, const K, SetOfT>::Const_Iterator const_iterator;const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}bool insert(const K& key){return _ht.Insert(key);}void print(const unordered_set<int>& s){const_iterator it = s.begin();while (it != s.end()){cout << *it << " ";it++;}cout << endl;}void testset(){unordered_set<int> s;s.insert(1);s.insert(2);print(s);}private:HashTable<K, const K,SetOfT> _ht;
typedef typename HashTable<K, pair<const K, V>, MapOfT>::Iterator iterator;typedef typename HashTable<K, pair<const K, V>, MapOfT>::Const_Iterator const_iterator;iterator begin(){return _ht.Begin();}iterator end(){return _ht.End();}const_iterator begin() const{return _ht.Begin();}const_iterator end() const{return _ht.End();}bool insert(const pair<const K,V>& kv){return _ht.Insert(kv);}private:HashTable<K, pair<const K, V>,MapOfT> _ht;};

1.5实现operator[]

 operator[]的实现依赖于insert,而我们现在的insert还不是最终版本,接下来我们进行修改

第一步:修改Find()

Iterator Find(const K& key){Func fc;KeyOfT  kot;size_t hash0 = fc(key) % _tables.size();Node* cur = _tables[hash0];while (cur){if (kot(cur->_data) == key) return {cur,nullptr};cur = cur->_next;}return End();}

若找到了就用当前的cur构建迭代器返回,没有找到就返回end迭代器

第二步:修改insert

pair<Iterator,bool> Insert(const T& data){KeyOfT kot;Func fc;//不允许冗余Iterator it = Find(kot(data));if (it != End()) return {it,false};//负载因子为1就扩容if (_n == _tables.size()){vector<Node*> newtable (2 * _tables.size());for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){//将旧的表中节点挪到新表中Node* next = cur->_next;size_t hash0 = fc(kot(cur->_data)) % newtable.size();//头插cur->_next = newtable[hash0];newtable[hash0] = cur;//更新curcur = next;}_tables[i] = nullptr;}newtable.swap(_tables);}//头插size_t hash0 = fc(kot(data)) % _tables.size();Node* newnode = new Node(data);newnode->_next = _tables[hash0];_tables[hash0] = newnode;_n++;return { {newnode,this},true };}

第三步:实现operatoar[]

V& operator[](const K& key){pair<iterator, bool> p = insert({ key,V() });return p.first->second;}

1.6在unordered_set和unordered_map中增加一个模板参数

 增加一个Func参数,主要是方便我们写仿函数控制key的数据类型可以转换为可以取模的类型

unordered_map的控制:

template<class K, class V, class Func = HashFunc<K>>class unordered_map{struct MapOfT{const K& operator()(const pair<const K,V>& data){return data.first;}};

unordered_set的控制:

template<class K, class Func = HashFunc<K>>class unordered_set{struct SetOfT{const K& operator()(const K& key){return key;}};

http://www.dtcms.com/wzjs/192272.html

相关文章:

  • 葫芦岛高端网站制作在线seo工具
  • 外贸做的亚马逊网站是哪个新媒体运营培训
  • 巢湖网站建设费用发布新闻
  • 网站建设佰首选金手指四投广告哪个平台好
  • 长沙做网站设计服务之家网站推广
  • ps教程自学网新手教程详细步骤杭州优化商务服务公司
  • 免费网站应用软件网站优化排名易下拉系统
  • 销售性网站建设需求aso关键词搜索优化
  • 优秀金融网站设计舆情监测软件
  • 红酒企业网站建设大学生网页制作成品模板
  • 郑州网站设计收费低seo日常工作
  • 昌吉做网站河南公司网站建设
  • 如何网站优化排名成人电脑速成培训班
  • 菏泽手机网站建设app推广软件有哪些
  • 做微网站那pc端显示啥网站网络推广公司
  • 广州网站建设网络推广公司app开发价格表
  • 南京高端网站制作公司百度一下电脑版首页网址
  • 中山做网站价格博客网站登录
  • 旅游网站开发外文翻译百度网站优化方案
  • 中国设计网appseo教学免费课程霸屏
  • 前几年做啥网站致富百度首页排名优化服务
  • 企业网站建设内容报价seo搜索引擎优化工资
  • 珠海市网站建设公司千锋教育靠谱吗
  • 在哪个网站上面可以接项目做宁德seo培训
  • 网站建设现状 数据企业网搭建
  • 外国做的福利小视频在线观看网站武汉做搜索引擎推广的公司
  • 如何java做网站seo网络推广员招聘
  • 我有域名和云服务器怎么做网站网搜网
  • 网站推广百度优化百度竞价推广的技巧
  • 网站优化的目的如何制作自己的公司网站