交换两个变量而不使用第三个改进性能?

时间:2014-08-21 19:36:09

标签: algorithm optimization swap

2 个答案:

答案 0 :(得分:1)

甚至没有计算机架构的观点。

例如,如果我使用位操作交换两个整数,如下所示:

a ^= b;
b ^= a;
a ^= b;

在CPU中运行的是:

mov reg1, &a
mov reg2, &b
xor reg1, reg2
xor reg2, reg1
xor reg1, reg2

可以轻易说出的是reg1和reg2相互依赖。

现代CPU使用指令流的无序执行。也就是说,如果这些指令不依赖于彼此的结果,则执行多个指令。因此,现代CPU在同一时刻运行多个指令是正常的。

但是如果使用临时变量怎么办? 死得很轻松。现代CPU通常具有指令级支持。

xchg reg1, reg2

进行。

顺便说一下,不要过多关注装配。它在不同的架构中有所不同。仅用于演示。

答案 1 :(得分:0)

没有。至少在Java中。使用第三个变量交换两个基本整数是最快的(也是最容易理解的)。

我写了这段代码来测试它。它比较了我在各种答案中找到的两种最常用的技术:使用减法交换和使用按位xor进行交换。

package compareswapmethods;

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;


public class CompareSwapMethods {

    private static final Random rand = new Random();
    private static final int ITERATIONS = 1000000;
    private static final int MIN_LENGTH = 2;
    private static final int MAX_LENGTH = 100;
    private static final int MIN_VAL = -100;
    private static final int MAX_VAL = 100;

    public static void main(String[] args)
    {
        System.out.println("press enter to start");
        Scanner in = new Scanner(System.in);
        in.nextLine();
        for(int i = 0; i < ITERATIONS; i++)
        {
            int[] sample1, sample2, sample3;
            sample1 = generateRandomArray(MIN_LENGTH, MAX_LENGTH, MIN_VAL, MAX_VAL);
            sample2 = Arrays.copyOf(sample1, sample1.length);
            sample3 = Arrays.copyOf(sample1, sample2.length);
            /*System.out.println(Arrays.toString(sample1));
            System.out.println(Arrays.toString(sample2));
            System.out.println(Arrays.toString(sample3));*/

            int x = randomVal(0, sample1.length-1);
            int y = randomVal(0, sample1.length-1);
            thirdv(sample1, x, y);
            subtractive(sample2, x, y);
            bitwise(sample3, x, y);
            /*System.out.println(Arrays.toString(sample1));
            System.out.println(Arrays.toString(sample2));
            System.out.println(Arrays.toString(sample3));
            System.out.println("-");*/
        }
        System.out.println("done");
    }

    /*swap elements in array using third variable*/
    public static void thirdv(int[] arr, int x, int y)
    {
        int temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

    /*swap elements in array using subtraction variable*/
    public static void subtractive(int[] arr, int x, int y)
    {
        arr[x] = arr[x] + arr[y];
        arr[y] = arr[x] - arr[y];
        arr[x] = arr[x] - arr[y];
    }

    /*swap elements in array using bitwise xor*/
    public static void bitwise(int[] arr, int x, int y)
    {
        arr[x] ^= arr[y]; 
        arr[y] ^= arr[x];
        arr[x] ^= arr[y]; 
    }

    /*returns random int between [min, max]*/
    public static int randomVal(int min, int max)
    {
        return min + rand.nextInt(max - min + 1);
    }

    /*creates array of random length, between [min, max],
    and calls poppulateArray on it*/
    public static int[] generateRandomArray(int minLength, int maxLength, int minVal, int maxVal)
    {
        int[] arr = new int[minLength+rand.nextInt((maxLength-minLength)+1)];
        populateArray(arr, minVal, maxVal);
        return arr;
    }

    /*assigns random values, in the range of [min, max]
    (inclusive), to the elements in arr*/
    public static void populateArray(int arr[], int min, int max)
    {
        Random r = new Random();
        for(int i = 0; i < arr.length; i++)
            arr[i] = min+r.nextInt((max-min)+1);
    }

}

然后我使用VisualVM进行分析,结果如下:

screenshot of results in VisualVM

结果在测试之间做了很多,但我总是看到thirdv方法占用最短的CPU时间。