值交换的两种方法及其效率分析
2004-08-25 20:34
429 查看
比如, 我们有两个数a, b要交换值, 我们一般通过这样的方式来达到目的:
int c;
c = a;
a = b;
b = c;
这样来达到交换a, b值的目的;
经常使用位操作的人, 或者会有这样的"高招":
a ^= b;
b ^= a;
a ^= b;
这样也能交换a, b的值, 而且还少用了一个中间参数.
现在我们看到了我们交换值的两种做法,到底哪一种更好呢?
呵呵, 看看反应, 我们将从汇编, 事实(时间)等各个角度来得出结果.
c = b;
mov eax,dword ptr [ebp-8]
mov dword ptr [ebp-0Ch],eax
b = a;
mov ecx,dword ptr [ebp-4]
mov dword ptr [ebp-8],ecx
a = c;
mov edx,dword ptr [ebp-0Ch]
mov dword ptr [ebp-4],edx
总共有六条汇编指令;
我们再看看后一种方法的汇编指令条数:
a ^= b;
mov eax,dword ptr [ebp-4]
xor eax,dword ptr [ebp-8]
mov dword ptr [ebp-4],eax
b ^= a;
mov ecx,dword ptr [ebp-8]
xor ecx,dword ptr [ebp-4]
mov dword ptr [ebp-8],ecx
a ^= b;
mov edx,dword ptr [ebp-4]
xor edx,dword ptr [ebp-8]
mov dword ptr [ebp-4],edx
怎么样? 后一种方法足足比前一种方法多了三条指令. 当然, 更直观的方法还是来点测试, 我们可以更显而易见的看到对比的结果, 而且这个结果也反映了一个比较普遍的策略.
第一种方法:
int a = 9;
int b = 8;
int c;
int nCount;
nCount = GetTickCount();
printf("Start time: %d/n", nCount);
for (int i = 0; i < 100000000; i++)
{
c = a;
a = b;
b = c;
}
nCount = GetTickCount();
printf("End time: %d/n", nCount);
结果是:
Start time: 38830024
End time: 38830395
用了371 ms.
第二种方法:
int a = 9;
int b = 8;
int nCount;
nCount = GetTickCount();
printf("Start time: %d/n", nCount);
for (int i = 0; i < 100000000; i++)
{
a ^= b;
b ^= a;
a ^= b;
}
nCount = GetTickCount();
printf("End time: %d/n", nCount);
结果是:
Start time: 38955024
End time: 38956125
用了1001ms.
两者的结果在大量重复操作下都呈现数量级上的差距了.
从这两种方法我们可以看出, 虽然第一种方法时间少, 但是其增加了一个变量的消耗, 第二种方法虽然时间多, 但是节省了一个变量的空间, 但是其损失的时间效率确是很客观的.
在某些场合, 时间很重要, 而存储器容量显然还没有到捉襟见肘的时候, 第一种方法显然是合适的, 它其实就是一个”空间换时间”的策略体现, 而且它更容易理解; 而第二种在理解上就比较不那么容易(你也许应该自己做一下逻辑运算才能知道它们确实交换了值:), 而且其时间损失是显而易见的(在电量比较极其的设备中, 这也是不能容忍的). 这也是第二中方法几乎快销声匿迹的原因了. 有一次在某论坛里看到有人拿出了第二种方法的代码, 还说是绝妙的三行代码, 呵呵.
int c;
c = a;
a = b;
b = c;
这样来达到交换a, b值的目的;
经常使用位操作的人, 或者会有这样的"高招":
a ^= b;
b ^= a;
a ^= b;
这样也能交换a, b的值, 而且还少用了一个中间参数.
现在我们看到了我们交换值的两种做法,到底哪一种更好呢?
呵呵, 看看反应, 我们将从汇编, 事实(时间)等各个角度来得出结果.
c = b;
mov eax,dword ptr [ebp-8]
mov dword ptr [ebp-0Ch],eax
b = a;
mov ecx,dword ptr [ebp-4]
mov dword ptr [ebp-8],ecx
a = c;
mov edx,dword ptr [ebp-0Ch]
mov dword ptr [ebp-4],edx
总共有六条汇编指令;
我们再看看后一种方法的汇编指令条数:
a ^= b;
mov eax,dword ptr [ebp-4]
xor eax,dword ptr [ebp-8]
mov dword ptr [ebp-4],eax
b ^= a;
mov ecx,dword ptr [ebp-8]
xor ecx,dword ptr [ebp-4]
mov dword ptr [ebp-8],ecx
a ^= b;
mov edx,dword ptr [ebp-4]
xor edx,dword ptr [ebp-8]
mov dword ptr [ebp-4],edx
怎么样? 后一种方法足足比前一种方法多了三条指令. 当然, 更直观的方法还是来点测试, 我们可以更显而易见的看到对比的结果, 而且这个结果也反映了一个比较普遍的策略.
第一种方法:
int a = 9;
int b = 8;
int c;
int nCount;
nCount = GetTickCount();
printf("Start time: %d/n", nCount);
for (int i = 0; i < 100000000; i++)
{
c = a;
a = b;
b = c;
}
nCount = GetTickCount();
printf("End time: %d/n", nCount);
结果是:
Start time: 38830024
End time: 38830395
用了371 ms.
第二种方法:
int a = 9;
int b = 8;
int nCount;
nCount = GetTickCount();
printf("Start time: %d/n", nCount);
for (int i = 0; i < 100000000; i++)
{
a ^= b;
b ^= a;
a ^= b;
}
nCount = GetTickCount();
printf("End time: %d/n", nCount);
结果是:
Start time: 38955024
End time: 38956125
用了1001ms.
两者的结果在大量重复操作下都呈现数量级上的差距了.
从这两种方法我们可以看出, 虽然第一种方法时间少, 但是其增加了一个变量的消耗, 第二种方法虽然时间多, 但是节省了一个变量的空间, 但是其损失的时间效率确是很客观的.
在某些场合, 时间很重要, 而存储器容量显然还没有到捉襟见肘的时候, 第一种方法显然是合适的, 它其实就是一个”空间换时间”的策略体现, 而且它更容易理解; 而第二种在理解上就比较不那么容易(你也许应该自己做一下逻辑运算才能知道它们确实交换了值:), 而且其时间损失是显而易见的(在电量比较极其的设备中, 这也是不能容忍的). 这也是第二中方法几乎快销声匿迹的原因了. 有一次在某论坛里看到有人拿出了第二种方法的代码, 还说是绝妙的三行代码, 呵呵.
相关文章推荐
- 关于pymongo两种连接方法MongoClient和Connection连接mongodb的写入效率分析
- [C语言] 数据结构-算法效率的度量方法-事前分析估算方法
- 三行代码实现.NET MVC统计显示页面的执行时间 超简单的实现方法 分析页面执行效率
- 两个变量值交换的方法,你想到了吗?哪种更实用,效率更高,请自己作答!
- 分析两种Dump(崩溃日志)文件生成的方法及比较
- Matlab提供的两种聚类分析方法
- 彩票的两种分析方法
- mybatis学习之路----批量更新数据两种方法效率对比
- Ajax中解析Json的两种方法对比分析
- 交换变量的值的两种有趣方法(位操作与算术法)
- eclipse/MyEclipse格式化代码失灵原因分析及其解决方法
- 遍历hashmap的两种方法及分析
- iOS Swift 数组 交换元素的两种方法
- Java List遍历方法 及其效率对比
- CRC原理及其逆向分析方法
- 不用临时的变量 交换两个数的两种方法
- 【Android游戏开发之十】(优化处理)详细剖析Android Traceview效率检视工具,分析程序运行速度!并讲解两种创建SDcard方式!
- Java交换两个数的四种方法和效率
- Android中system.img的两种格式及其相互转换方法
- java 遍历arrayList的四种方法及其效率对比