tags:

views:

200

answers:

6

What kind of algorithm Array.Reverse(string a), uses behind the scene to reverse the string?

+8  A: 

Probably a standard in-place reversal algorithm.

function reverse-in-place(a[0..n])
 for i from 0 to floor(n/2)
     swap(a[i], a[n-i])

Sources

polygenelubricants
This is a good answer in general. But notice the OP is asking about .NET (he clarified this in a comment). Reversing a string in-place in .NET is not possible without resorting to some evil tactics. And doing so by employing those tactics leads to bad things. See my answer!
Dan Tao
+2  A: 

The algorithm is probably using two pointers i and j that start at 0 and length-1 respectively. Then the characters at position i and j are swapped (with the help of a temporal variable) and i is incremented and j decremented by 1. These steps are repeated until both pointers reach each other (ij).

In pseudo-code:

i := 0;
j := a.length-1;
while (i < j) do
    tmp := a[i];
    a[i] := a[j];
    a[j] := tmp;
    i := i+1;
    j := j-1;
endwhile;
Gumbo
+2  A: 

Here's a general-purpose, language-independent, question-appropriate answer: It copies the input string to the output string, reading from one end and writing to the other.

High Performance Mark
+7  A: 

UPDATE: See the bottom of this answer for one truly horrifying ramification of reversing a string in-place in .NET.


"Good" Answer

In .NET, there's no Array.Reverse overload that takes a string. That said, here's how one might be implemented if it were to exist:

static string ReverseString(string str) {
    char[] reversed = new char[str.Length];
    for (int i = 0; i < reversed.Length; ++i)
        reversed[i] = str[str.Length - 1 - i];
    return new string(reversed);
}

Note that in .NET this method has to return a string, since the System.String type is immutable and so you couldn't reverse one in-place.


Scary Answer

OK, actually, it is possible to reverse a string in-place in .NET.

Here's one way, which requires compiling in unsafe mode:

static unsafe void ReverseString(string str) {
    int i = 0;
    int j = str.Length - 1;

    fixed (char* fstr = str) {
        while (i < j) {
            char temp = fstr[j];

            fstr[j--] = fstr[i];
            fstr[i++] = temp;
        }
    }
}

And here's another way, which uses reflection and does not need to be compiled in unsafe mode:

static void ReverseString(string str) {
    int i = 0;
    int j = str.Length - 1;

    // what a tricky bastard!
    MethodInfo setter = typeof(string).GetMethod(
        "SetChar",
        BindingFlags.Instance | BindingFlags.NonPublic
    );

    while (i < j) {
        char temp = str[j];

        setter.Invoke(str, new object[] { j--, str[i] });
        setter.Invoke(str, new object[] { i++, temp });
    }
}

Totally inadvisable and reckless, yes -- not to mention that it would likely have horrendous performance. But possible nonetheless.


The Horror

Oh, and by the way, in case there's any doubt in your mind whatsoever that you should never do anything like this: be aware that either of the ReverseString methods I've provided above will actually allow you to write the following utterly bizarre program:

ReverseString("Hello!");
Console.WriteLine("Hello!");

The above code will output, believe it or not*:

!olleH

So yeah, unless you want all hell to break loose in your code, don't reverse a string in-place. Even though technically you can ;)

*You can try it for yourself if you don't believe me.

Dan Tao
string is nothing but array of character (char[]), when you pass an string it think it as a char[].FYI I could pass string and able to reverse it using Array.Reverse
ManojTrek
Does it not depend on the encoding which string uses internally? Check out: http://www.yoda.arachsys.com/csharp/strings.html
Moron
@ManojTrek: string is an alias to System.String, which is not 'nothing by an array of characters'. It contains a collection of chars within it, which you can get a copy of, but the String itself is immutable, and cannot be modified once created. http://msdn.microsoft.com/en-us/library/system.string%28v=VS.71%29.aspx
Farrell
@ManojTrek: That is simply not true. A string may *internally* use an array of `char`, but it's not the same thing. You can modify the value at a specified index of an array; try setting `str[i] = 'c'` and you'll see it doesn't compile.
Dan Tao
@ManojTrek: As for passing a string to `Array.Reverse`: just give it a try. You'll see it doesn't compile.
Dan Tao
Aplogize, yes you are right need to use String.ToCharArray() method to convert to character array, before passing to Array.Reverse.
ManojTrek
@MajojTrek: Just be aware that this is going to reverse *the array returned by `ToCharArray`*, which is a *copy* of the original string. Then, yes, you can easily create a new string from this reversed array. Again: **you cannot reverse a string in-place in .NET**.
Dan Tao
Yes Understood.
ManojTrek
@ManojTrek: ...er, addendum: you cannot reverse a string in-place in .NET *without using unsafe code* ;)
Dan Tao
@ManojTrek: Yet another correction: you can do it even without using unsafe code (using reflection)! But, obviously, I don't advise it.
Dan Tao
what a great answer. +1
Markust
+3  A: 

According to Reflector, Array.Reverse(Array) (there's no string variation) first calls something called TrySZReverse, for which I can't find the implementation. I assume it's some sort of heavily optimized native method..

If that fails, it does something like this:

int num = index;
int num2 = (index + length) - 1;
while (num < num2)
{
    object obj2 = objArray[num];
    objArray[num] = objArray[num2];
    objArray[num2] = obj2;
    num++;
    num2--;
}

So, an in place algorithm, where it swaps the values at each end, then moves inward, repeatedly.

Blorgbeard
A: 

My suggestion:

    private string Reverse(string text)
    {
        char[] c = text.ToCharArray(0, text.Length);
        Array.Reverse(c);
        return new string(c);
    }
spookycoder