Friday, March 4, 2011

WAP fro Generica Swap & Simple Swp of two variable all possible method

Swapping two variables

Swapping two variables refers to mutually exchanging the values of two variables. For Example: If X & Y are two integer variable in C, such that

int X = 5;

int Y = 10;

Than after swapping X should be 10 and Y should be 5. Swapping can be done in variety of ways. We discuss few methods below

Method 1: Using Temporary variable
view sourceprint?
1 /* Let t be a temporary variable */
2 int t = X;
3 X = Y;
4 Y = t;

Above Algorithm looks very light & simple. It indeed is, if X & Y are integers.

What if, we are in C++ and X & Y are Objects of user defined class. Creating a temporary variable means constructor and Destructor will be called. Also there are two assignments (the first statement is initialization and not assignment), so Overloaded assignment operator will be called twice. This is a huge amount of task, especially when the Class is heavy.

What if the class has nested objects of another class, which are constructed in the Construction and destroyed in the destructor? Also to further complicate, let us consider the Class inheritance hierarchy, So Constructors of all the Base classes will be called.

But this method may be the only way to swap two objects in many cases.

So, as Himesh Reshammiya says “It’s complicated” !

Method 2: Using XOR operator.


view sourceprint?
1 // Swaping using XOR
2 X = X ^ Y;
3 Y = X ^ Y;
4 X = X ^ Y;

This method does not use the temporary object and use bit-wise operator which is believed to be more compact than other operators (Compiler dependent).

The disadvantage of this method is that it can only be applied to low-level data types like integers & characters (char, short, int, long). C & C++ does not allow bit-wise operation on non-integral operands.

A Major flaw in this algo is that it won’t work if X & Y uses same memory location. The contents of that location will be Zero when the first statement is executed.

view sourceprint?
1 void swap(int *x, int * y){
2 // this check is compulsory, else it may not work properly for cases
3 // where x & y points to the same memory location.
4 if(x != y)
5 x ^= y ^= x ^=y;
6 }

Same Problem will occur if x & y are references to the same memory location.

Method 3: Using +,- operator.
view sourceprint?
1 X = X + Y;
2 Y = X - Y;
3 X = X - Y;

this method can however, only be applied on numeric values.

If we have addition and subtraction overloaded for a user defined type and we accidently try to swap using the above code, then we may run into bigger problems, because the compiler will not complain and the result may not be what we expect it to be.

The issue of arithmetic overflow is also there. For Example: Consider a hypothetical environment where the maximum limit of integers is 100, and we want to swap X & Y with values 40 & 70 respectively. Swapping them using temporary variable (Method 1) or XOR (Method 2) will be correct but in this case the result will be undefined because 40 + 70 = 110 will result in an integer value overflow.

Note: In most of the environments, integers are stored in 2′s complement notation. If we perform above addition and subtraction in 2′s complement notions, then the result will be correct. But that is only because of the cyclic nature of 2′s complement representation and it is not guaranteed by the language.

Method 4: Using *, / operators

The above (Method 3) can be used with multiplication & divide operators in place of +, – operators.

Method 5: Swapping Pointers

Swapping pointers pointing to two different memory locations is very different from swapping the contents of those memory locations, though the results, in some cases, may be similar (not same).

For Example: If you want to swap two variables on heap and only one pointer points to each memory location, swapping the pointers will look similar to swapping the contents of the two memory locations.

Let ptr1 & ptr2 are two integer pointers pointing to memory locations containing 50 & 70 respectively,

then after swapping ptr1 and ptr2 will result in the below memory snap-shot:

Please note that if there is a third pointer ptr3 which also points to memory containing 50, then value-at ptr3 (*ptr3) will not change. But if we swap the contents of memory locations then *ptr3 will also be 70.

Either swapping of pointers or swapping the actual contents of the memory should be done depends on the requirements.

Since pointer variables are of fixed size and are non-negative integers, the XOR method of swapping can be used to swap two pointers.

If we swap the contents and not the pointers then we may end up using method 1 (particularly if we are dealing with user defined classes). And as discussed above it will have the complications of object creation, destruction & assignment operator calling.

Method 6: Generic Swapping

Using generic pointers or Macros in C language (void*) or templates in C++, we can define a generic swap function, which can swap two variable of any given datatype. (The macros may be error prone, though):

Generic pointers
view sourceprint?
1 void swap(void *vp1, void *vp2, int size)
2 {
3 char buffer[large]; // Large is a constant
4 memcpy(buffer,vp1,size);
5 memcpy(vp1,vp2,size);
6 memcpy(vp2,buffer,size);
7 }

Macro
view sourceprint?
1 #define SWAP(x, y, data_type) {data_type t=x; x=y; y=t; }

But the above macro does not work for all types and is more error prone than the other two variations.

Templates
view sourceprint?
1 template void swap(T&a, T &b)
2 {
3 T temp;
4
5 temp = a;
6 a = b;
7 b = temp;
8 }

In the above case the variables are passed by reference so that the actual arguments will get swapped. By default the values are passed by values and hence will swap the local variables of a function. To call the above template function for integers ,

swap(a,b);

No comments :