要求:給定一個字串,將字串逆轉。例如給定“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