三路快速排序以及双向扫描改进尝试

 

三路快速排序用三个指针来标注大于、等于、小于v的区域边界。三路快速排序比较省事的实现是只用一个指针(i)来从左向右遍历判断整个数组,这样在右侧元素大于或小于v的时候都要进行频繁的交换

 1         public static void Quick3way1(IComparable[] a)
 2         {
 3             Q3wPartition(a, 0, a.Length - 1);
 4         }
 5 
 6 
 7         private static void Q3wPartition(IComparable[] a, int lo, int hi)
 8         {
 9             if (lo >= hi) return;
10             int lt = lo, i = lo + 1, gt = hi;
11             IComparable v = a[lo];
12             int cmp;
13 
14             while (i <= gt)  // gt长期指向未处理的数,所以最后一轮i==gt
15             {
16                 cmp = a[i].CompareTo(v);  // 只用i来扫描判断值大小
17                 if (cmp > 0)
18                     Swap(a, i, gt--);  // 交换完后gt自减,所以gt长期指向未处理的数
19                 else if(cmp < 0)
20                     Swap(a, lt++, i++);
21                 else i++;
22             }
23             Q3wPartition(a, lo, lt - 1);
24             Q3wPartition(a, i, hi);
25         }

 

尝试用两个指针分别从左右向中间扫描判断,先让左指针开始搜索,当左指针扫描到大于v的值时,等右指针搜索,直到右指针扫描到需要处理的值时才和左指针指向的值交换

 1         public static void Quick3way2(IComparable[] a)
 2         {
 3             Q3w2Partition(a, 0, a.Length - 1);
 4         }
 5 
 6 
 7         public static void Q3w2Partition(IComparable[] a, int lo, int hi)
 8         {
 9             if (hi <= lo) return;   //递归结束
10 
11             int lt, gt, i, cmp;
12             lt = lo;
13             i = lo+1;
14             gt = hi;
15             IComparable v = a[lo];
16 
17             while (i <= gt)
18             {
19                 cmp = a[i].CompareTo(v);
20                 if (cmp == 0) 
21                     i++;
22                 else if (cmp < 0)
23                     Swap(a, lt++, i++);
24                 else   //a[i] > v时,从右开始扫描
25                 {
26                     while (gt > i)
27                     {
28                         cmp = a[gt].CompareTo(v);
29                         if (cmp == 0)
30                         {
31                             Swap(a, i++, gt);  //a[i],a[gt]一同归位
32                             break;
33                         }
34                         else if (cmp < 0)
35                         {
36                             IComparable temp = a[gt];
37                             a[gt] = a[i];
38                             a[i++] = a[lt];
39                             a[lt++] = temp;  //a[i],a[gt]归位
40                             break;
41                         }
42                         gt--;   //cmp>0,a[gt]自然归位,再循环n轮直到找到1个a[gt]<=v为止a[i]归位
43                     }
44                     gt--;   //当gt自减到等于i时,还要再自减一次以退出外循环
45                 }
46             }
47             Q3w2Partition(a, lo, lt - 1); 
48             Q3w2Partition(a, i, hi);
49         }

 

测试代码太长,先把主要的贴上来吧

        static void Main(string[] args)
        {
            SortTest2();
        }


        /// <summary>
        /// 批量分组测试两种算法
        /// </summary>
        public static void SortTest2()
        {
            int scale = 1000000;

            // 构造10个随机数组并赋值
            SortTest[] sortTests = new SortTest[10];
            for (int i = 0; i < 10; i++)
            {
                sortTests[i] = new SortTest(scale, 1, 1000);
            }

            // 构造10个计时器
            Stopwatch[] sw = new Stopwatch[10];
            for (int i = 0; i < 10; i++)
            {
                sw[i] = new Stopwatch();
            }

            // 前5个用来测试第一个算法,后5个测试第二个
            Console.WriteLine("Q3way1: ");
            for (int i = 0; i < 5; i++)
            {
                sw[i].Start();
                QuickSort.Quick3way1(sortTests[i].Arr);  // 实现1
                sw[i].Stop();
                Console.Write($"\t[{i}]Array is sorted: " + sortTests[i].IsSorted());
                Console.WriteLine("\tspends: " + sw[i].Elapsed);
            }
            Console.WriteLine("\nQ3way2: ");
            for (int i = 5; i < 10; i++)
            {
                sw[i].Start();
                QuickSort.Quick3way2(sortTests[i].Arr);  // 实现2
                sw[i].Stop();
                Console.Write($"\t[{i}]Array is sorted: " + sortTests[i].IsSorted());
                Console.WriteLine("\tspends: " + sw[i].Elapsed);
            }
        }


        /// <summary>
        /// 生成随机整数组成的IComparable数组
        /// </summary>
        /// <param name="a"></param>
        /// <param name="scale"></param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        public static void GetRandomArray(IComparable[] a, int scale, int minValue, int maxValue)
        {
            if (a.Length < scale) return;
            // 用系统时间作为随机种子
            Random rd = new Random(unchecked((int)DateTime.Now.Ticks));
            
            for (int i = 0; i < scale; i++)
            {
                a[i] = rd.Next(minValue, maxValue);
            }
            
        }


        /// <summary>
        /// 检验数组是否升序
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public bool IsSorted()
        {
            for (int i = 1; i < arr.Length; i++)
            {
                if (arr[i].CompareTo(arr[i - 1]) < 0)
                    return false;
            }
            return true;
        }

 

 

 

看起来有那么一点点点点点提升了

 

 

 

posted @ 2021-10-31 11:31  猫也  阅读(76)  评论(0)    收藏  举报