C++变量和STL容器的交换
变量交换#
现在有两个int
型变量x
和y
,需要将x
和y
的值进行交换
临时变量版#
这样显然是不行的:
复制x=y;
y=x;
因为当x
被赋值为y
,那么x
和y
所表示的均为原来y
的值,原来x
表示的数据将丢失
不难想到使用一个临时变量tmp
暂存其中一方的数据:
复制int tmp=x;
x=y;
y=tmp;
算术运算版#
之前的方法需要使用额外的变量来实现,那么有没有不使用额外变量的方法呢?当然是有的:
复制x=x+y;
y=x-y;
x=x-y;
语句非常对称也非常精妙,第一句将x
赋值为x
与y
的和,这样原来的x
仍然可以通过x-y
表示出来,而交换后的y
就是原来的x
,所以第二句赋值语句就将y
赋值成了原来的x
,此时x
仍然表示原来两个变量的和,所以交换后的x
也即原来的y
的值就是x-y
位运算版#
复制x^=y;
y^=x;
x^=y;
这个可以说是 xor 艺术了,原理与上一种类似,但是由于是位运算,运算速度要优于前面一种
汇编版#
复制__asm
{
mov eax,[x]
xchg eax,[y]
mov [x],eax
}
同样也是三行,不过之前的如果编译成汇编语言肯定不止三行,所以这个版本在性能和占用空间上碾压前三者
不过应该不会有人这么用的,仅供观赏,要慎用
函数版#
C++中提供了用于变量交换的swap
函数,只需要把两个变量传入即可:
复制swap(x,y)
swap
函数的内部实现:
复制template <class _Ty>
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept { // forward _Arg as movable
return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}
#if _HAS_CXX17
template <class _Ty, enable_if_t<is_move_constructible_v<_Ty> && is_move_assignable_v<_Ty>, int> _Enabled>
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
template <class _Ty, int _Enabled>
#endif // _HAS_CXX17
_CONSTEXPR20 void swap(_Ty& _Left, _Ty& _Right) noexcept(
is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) {
_Ty _Tmp = _STD move(_Left);
_Left = _STD move(_Right);
_Right = _STD move(_Tmp);
}
可以发现其内部机理与第一种方法类似,只是用了泛型并且增加了一些修饰
STL容器交换#
两个对象之间的交换,我们就没必要考虑时间复杂度的常数问题,而应该考虑与数据量的相关性
首先先考虑两个普通的int
数组x[1048576]
,y[1048576]
的交换,朴素的做法是对其中的每一个元素做一次交换:
复制for(int i=0;i<1048576;i++) swap(x[i],y[i]);
swap
函数也提供了两个数组交换的接口,与上面的实现过程一致
复制swap(x,y)
这样的时间复杂度是 ,换个角度思考,两个数组事实上只是两块内存中的连续单元,不像同一个数组中两个元素进行交换会影响结果,它们交换与否丝毫不影响算法的正确性,内容的交换等效于对它们的变量名进行交换,但是C++又不支持动态更改变量名,所以我们需要使用指针或引用,交换时也仅需交换指针或引用:
复制int *p1=x,*p2=y;
swap(p1,p2);
正是基于这个思想,stl的许多容器进行swap
操作的时间复杂度都是 ,包括:vector
,list
,map
,set
,deque
,
而priority_queue
,queue
,stack
在开C++11时为 ,否则为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构