要求:给定一个字符串,将字符串逆转。例如给定“welcome to caochao's blog !”,要求输出“! golb s'oahcoac ot emoclew”。
初次看题时,想到的解法很可能就是倒序遍历字符串,逐位取字符,然后拼成新字符串,新字符串即为逆转后字符串。代码如下:
/// <summary> /// 字符串逆转-StringBuilder实现 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string ReverseUsingStringBuilder(string str) { int length = str.Length; StringBuilder sb = new StringBuilder(length); for (int i = length - 1; i >= 0; i--) { sb.Append(str[i]); } return sb.ToString(); }
,但其实,还有一种更为简单的方法,简单令人难以置信,看到这个方法时不得不惊叹于.net framework方法的齐全。代码如下:
/// <summary> /// 字符串逆转-CharArray实现 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string ReverseUsingCharArray(string str) { char[] arr = str.ToCharArray(); Array.Reverse(arr); return new string(arr); }
但仔细一想,也许还有种更快的,至少从原理上看起来应该会快点。这种方法从字符串两端同时遍历,再逐位交换值。代码如下:
/// <summary> /// 字符串逆转-异或实现 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string ReverseUsingXor(string str) { char[] arr = str.ToCharArray(); int l = str.Length - 1; //交换值 for (int i = 0; i < l; i++, l--) { arr[i] ^= arr[l]; arr[l] ^= arr[i]; arr[i] ^= arr[l]; } return new string(arr); }
至此,讲完了字符串逆转的三种方法。也许看客还有更好的方法,就请在评论里留下您的高见吧。:-)
如同电影和电视剧时,最精彩的部分往往在后半部分。因此,小生的文章也把最重要的部分挪到了后面。笔者设计了一个测试方法,从而测试出以上三种字符串逆转方法的性能优劣。该方法如下:
public delegate string funcDelegate(string s); /// <summary> /// 测试方法 /// </summary> /// <param name="description">方法描述</param> /// <param name="func">测试方法</param> /// <param name="times">执行次数</param> /// <param name="str">测试字符串</param> public static void Benchmark(string description, funcDelegate func, int times, string str) { Stopwatch sw = new Stopwatch(); sw.Start(); for (int j = 0; j < times; j++) { func(str); } sw.Stop(); Console.WriteLine("方法{0}:调用{1}次,用时{2}.", description, times, sw.ElapsedTicks); }
还有一个生成随机字符串的方法,请看代码:
/// <summary> /// 生成指定长度随机字符串 /// </summary> /// <param name="length">字条串长度</param> /// <returns></returns> public static string RandomString(int length) { Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)))); } return sb.ToString(); }
接下来,主角隆重登场。请看Main入口方法:
static void Main(string[] args) { int[] lengths = new int[] { 1, 10, 15, 25, 50, 75, 100, 1000, 100000 }; foreach (int len in lengths) { //每个方法都执行10000次,力求精确 int iterations = 10000; //生成随机测试字符串 string testString = StringReverse.RandomString(len); //打印测试信息 StringReverse.Benchmark(String.Format("String Builder (测试字符串长度为{0})", len), StringReverse.ReverseUsingStringBuilder, iterations, testString); StringReverse.Benchmark(String.Format("Array.Reverse (测试字符串长度为{0})", len), StringReverse.ReverseUsingCharArray, iterations, testString); StringReverse.Benchmark(String.Format("Xor (测试字符串长度为{0})", len), StringReverse.ReverseUsingXor, iterations, testString); Console.WriteLine(); } Console.Read(); }
运行后看结果。结果在这里:
结论:从运行结果可以看出,
异或实现的逆转方法,随着字符串长度的递增,用时越来越长。但在字符串长度较小时,为三种方法中性能最好的。
StringBuilder实现的字符串逆转,无论字符串长度大小,都是性能最差的。个人估计是开辟新内存的开销带来的性能上的损失。
Array.Reverse实现的字符串逆转,这种最傻瓜的方法,却是在以上三种方法中性能表现最稳定的。个中原因,由看客们评价吧。
最后,附上stackoverflow上关于c#字符串逆转算法的一个讨论帖地址
http://stackoverflow.com/questions/228038/best-way-to-reverse-a-string-in-c-sharp-2-0