1.——使用string的append()代替+=
1.背景
背景:部分代码中对于string字符串的添加采用+=方式,经测验,append方式执行效率更高。
2.测验代码
#include<iostream>
#include<ctime>
#include<map>
using namespace std;
int main() {
for (int j = 0; j < 10; ++j) {
string strinfo;
clock_t startTime, endTime;
startTime = clock();//计时开始
for (long int i = 0; i < 20000000; i++) {
//strinfo += "大家好!";
strinfo.append("本次活动为:");
}
endTime = clock();//计时结束
cout << "The run time is: " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl; }
system("pause");
return 0; }
(1)使用append
(2)使用+=
3.原因basic_string.h:源码探究
//-------------------------------+=运算符重载部分---------------------------
//追加 string 类型字符串
basic_string&
operator+=(const basic_string& __str)
{ return this->append(__str); }
//追加 cstring 类型字符串
basic_string&
operator+=(const _CharT* __s)
{ return this->append(__s); }
//追加单个字符
basic_string&
operator+=(_CharT __c)
{
this->push_back(__c);
return *this;
}
#if __cplusplus >= 201103L
//追加字符类型的初始化列表
basic_string&
operator+=(initializer_list<_CharT> __l)
{ return this->append(__l.begin(), __l.size()); }
//-------------------------------append函数实现部分---------------------------
//追加 string 类型字符串
basic_string&
append(const basic_string& __str);
//追加部分 string 类型字符串
basic_string&
append(const basic_string& __str, size_type __pos, size_type __n);
//追加部分 cstring 类型字符串
basic_string&
append(const _CharT* __s, size_type __n);
//追加 cstring 类型字符串
basic_string&
append(const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->append(__s, traits_type::length(__s));
}
//追加多个字符
basic_string&
append(size_type __n, _CharT __c);
#if __cplusplus >= 201103L
//追加字符类型的初始化列表
basic_string&
append(initializer_list<_CharT> __l)
{ return this->append(__l.begin(), __l.size()); }
#endif // C++11
template<class _InputIterator>
basic_string& //附加给定范围内的多个字符
append(_InputIterator __first, _InputIterator __last)
{ return this->replace(_M_iend(), _M_iend(), __first, __last); }
可以看到+=部分代码为:
operator+=(const basic_string& __str) {
return this->append(__str);
}
所以+=本质还是调用的append,只不过是运算符重载。
4.结果建议代码后续采用append方式代替+=,从而提升服务器运行效率
参考资料:
2.——映射使用unordered_map代替map
1.背景
背景:项目代码中对于命令映射采用map方式,经测验,unordered_map方式执行效率更高。
2.测验代码
#include<iostream>
#include<ctime>
#include<map>
#include<unordered_map>
using namespace std;
// map<string, int> m_mCmdName; //命令映射表
unordered_map<string, int> m_mCmdName; //命令映射表
void SetCommandMap()
{
m_mCmdName["1"] = 1;
m_mCmdName["2"] = 2;
m_mCmdName["3"] = 3;
m_mCmdName["4"] = 5;
m_mCmdName["6"] = 6;
m_mCmdName["6"] = 6;
m_mCmdName["7"] = 6;
m_mCmdName["8"] = 6;
m_mCmdName["9"] = 6;
m_mCmdName["10"] = 6;
m_mCmdName["11"] = 6;
m_mCmdName["12"] = 6;
m_mCmdName["13"] = 6;
m_mCmdName["14"] = 6;
m_mCmdName["15"] = 6;
m_mCmdName["15"] = 6;
m_mCmdName["16"] = 6;
m_mCmdName["17"] = 6;
m_mCmdName["18"] = 6;
m_mCmdName["19"] = 6;
m_mCmdName["20"] = 6;
}
int main()
{
SetCommandMap();
int a;
for (int j = 0; j < 10; ++j) {
string strinfo;
clock_t startTime, endTime;
startTime = clock();//计时开始
for (long int i = 0; i < 1000000; i++) {
a= m_mCmdName["20"] ;
}
endTime = clock();//计时结束
cout << "The run time is: " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
}
system("pause");
return 0;
}
<1>在哈希表只有5个元素的情况下(1)使用map(2)使用unordered_map
<2>在哈希表表有20个元素的情况下
结论:可以发现,平均运行时间unordered_map更快,unordered_map效率是map的两倍,使用unordered_map可以将效率提升100%。
3.原因
basic_string.h:源码探究map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
4.优缺点以及适用处:
1.map:
优点:有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作 红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高 缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些
2.unordered_map:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间 适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map 总结:
内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。 但是unordered_map执行效率要比map高很多 对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。
map和unordered_map的使用
unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
4.结果运行效率方面:unordered_map最高,hash_map其次,而map效率最低
占用内存方面:hash_map内存占用最低,unordered_map其次,而map占用最高
结论:
- map是基于红黑树结构实现的。红黑树是一种平衡二叉查找树的变体结构,它的左右子树的高度差有可能会大于 1。所以红黑树不是严格意义上的平衡二叉树AVL,但对之进行平衡的代价相对于AVL较低, 其平均统计性能要强于AVL。红黑树具有自动排序的功能,因此它使得map也具有按键(key)排序的功能,因此在map中的元素排列都是有序的。在map中,红黑树的每个节点就代表一个元素,因此实现对map的增删改查,也就是相当于对红黑树的操作。对于这些操作的复杂度都为O(logn),复杂度即为红黑树的高度。
- unordered_map是基于哈希表(也叫散列表)实现的。散列表是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。散列表使得unordered_map的插入和查询速度接近于O(1)(在没有冲突的情况下),但是其内部元素的排列顺序是无序的。
在需要元素有序性或者对单次查询性能要求较为敏感时,请使用map,其余情况下应使用unordered_map。
unordered_map效率是map的两倍,使用unordered_map可以将效率提升100%。
建议代码后续采用unordered_map方式代替map,从而提升服务器运行效率
参考资料:
- https://blog.csdn.net/qq_21997625/article/details/84672775