现在的位置: 首页 > 综合 > 正文

c#字符串三种逆转方法及性能比较

2013年02月08日 ⁄ 综合 ⁄ 共 2975字 ⁄ 字号 评论关闭

要求:给定一个字符串,将字符串逆转。例如给定“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

抱歉!评论已关闭.