直接交换与临时空间交换算法比较
昨天在看到网上有问一段代码是什么作用,看了一下,是任意字符串逆序的功能。
大概是这样的。
char [] s =str.toString().toCharArray();
long now =0;
int begin =0 ;int end=s.length -1;
while(begin<end){
s[begin]=(char) (s[begin]^s[end]);
s[end]=(char) (s[end]^s[begin]);
s[begin]= (char) (s[begin]^s[end]);
begin++;
end--;
}
以前还真没见过这么写的,第一直觉,这种交换不需要分配临时空间,我们知道新增内存是非耗时的操作。所以没有太细考虑就直接回复这个算法的性能应该不错,会比用临时交换空间的算法性能高很多。
结果今天一上线,就看到网友的拍砖。说是这个直接交换没有用经典的用临时空间交换算法快。
哦,然后呢,我就仔细想了下。
temp =a;
a= b;
b=temp;
真是,都是三次运算,而且用于交换的临时空间,也不用每次都审请,只用一个单元空间就够了。
但是临时空间交换真的会比直接交换快很多吗?
对于“超标量处理器”这个也没什么直观的认识,写个程序试试吧。
对150000000个随机字符串进行操作,结果被震撼了。
直接交换排序用了 278ms
而临时空间交换只用了154ms
相差了一近倍。
为什么会差这么多能,看到了直接交换的char。异或算是Int类型,而char是8位的所以,会不会是由它影响的呢?把直接交换的代码粗暴的改一下,看看结果再说。
while(begin<end){
int b,e;
b=s[begin];
e=s[end];
b=b^e;
e=b^e;
b=b^e;
s[begin]=(char)b;
s[end] =(char)e;
begin++;
end--;
}
结果,只用了150ms。不过这段代码只比原先少了一个强转,也不会快差这么多啊。再对比一下,数组取值的操作数量,是与交换排序算法的相同都是4个。数组的取值的时间复杂度好像是O(1),而直接赋值有说忽略不计的,有说O(1)的。算了,也搞不清楚,还是直接上代码吧。
数组读取
str = RandomString.getInstance().randomAlpha(9999);
char [] s =str.toString().toCharArray();
long now = System.currentTimeMillis();
for (int i = 0; i < 1200000000; i++) {
char a =s[999];
}
long finish = System.currentTimeMillis();
System.out.println(finish -now+"ms" );//花费701ms
直接赋值
str = RandomString.getInstance().randomAlpha(9999);
char [] s =str.toString().toCharArray();
long now = System.currentTimeMillis();
char b =s[999];
for (int i = 0; i < 1200000000; i++) {
char a =b;
}
long finish = System.currentTimeMillis();
System.out.println(finish -now+"ms" ); //花费425ms
差不多就到这吧,对于技术真不能想当然,离真相差的不止十万八千里。
虽然到最后也没有比较出到低哪个快,但java差不多就基本这个情况,不过有一点,以后再使用数组进行读取的话,看来最好先赋给一个变量再进一步操作。有时间再用C语言试试。
附,感谢caozhy网友的指正。