通用快速排序算法

前 注:

这是自己平时根据自己需要写的一些小代码,为了避免再次数据丢失,所以放到网上来,未必对各看官有用。另外,这是根据个人想法而写,未必严谨和符合设计原则,若有任何不妥之处,还请不吝赐教。

说 明:

对于排序或查找算法而言,这些代码复用的一个难点在于:算法逻辑和数据集操作的代码是耦合在一起的。导致即使算法逻辑一样,但因为数据集类型的差异,也不得不重新实现整个算法。而我们所想要的算法复用,其实是算法逻辑的复用。因此,要复用算法,关键在于把算法逻辑抽取出来。由于一般情况下,算法的结构是数据集操作嵌入到算法逻辑过程中,因此,若能为数据集操作抽象出统一的接口,则算法逻辑就可以通用了。
如何为数据集操作抽象一个接口,应该为数据集定义一个基类吗?显然不可行,虽然.NET有一些集合类型的基础接口,但这些接口基本上没有提供排序所需操作的方法。而且并非所有的类型都有相同的基类型。因此,要抽象操作数据的接口,必须换个角度。
对于大部排序算法来说,涉及对数据集的操作无外乎:一、比较数据集中两个值;二、交换数据集中的两个值。只需设计这两个操作的接口即可。显然,如何比较比较数据要依数据类型和业务要求而定,而如何交换数据的值则与数据集结构和数据类型有关。另一方面,其实算法所决定的只有一点:要比较或交换的数据的位置,算法所关心的也只有一点:比较操作的结果(即返回值)。
综上,可以抽象一个这样的数据操作接口:一、比较,接受两个索引,返回比较结果;二、交换,接受两个索引,无返回值。算法调用这两个接口并传入索引,调用方负责实现比较两个索引处的值和交换两个索引处的值。
对于C#而言,此接口可以使用委托实现,而对于Java,则只能使用Interface来实现。相对来说,委托实现简洁一点,使用方需要做的工作也少一点,效率也应该会高一点。

另外,对于快速排序,其实只需要一个数据源的双向迭代访问器即可,不过这样实现起来想来应该比上述方法要繁琐一点。

示 例:

    class QuickSortTest
    {
        static byte[] Array;

        static Random Random = new Random();

        static QuickSorter QuickSorter = new QuickSorter();

        public static void Swap(int IdxA, int IdxB)
        {
            byte Temp = Array[IdxA];
            Array[IdxA] = Array[IdxB];
            Array[IdxB] = Temp;
        }

        public static int Compare(int IdxA, int IdxB)
        {
            return Array[IdxA] - Array[IdxB];
        }

        public static void Test()
        {
            int TestTimes = 1000;

            while (--TestTimes > 0)
            {
                Array = new byte[Random.Next(50)];

                Random.NextBytes(Array);

                Console.Write("\r\nBefore Sort : ");

                foreach (byte Data in Array)
                {
                    Console.Write(Data.ToString() + '\t');
                }

                QuickSorter.QuickSort(0, Array.Length - 1, Compare, Swap);

                Console.Write("\r\nAfter Sort : ");

                foreach (byte Data in Array)
                {
                    Console.Write(Data.ToString() + '\t');
                }

                if (Array.Length <= 1) continue;

                for (int Idx = 0; Idx < Array.Length - 1; Idx++)
                {
                    if (Array[Idx] > Array[Idx + 1])
                        Console.Write("\r\nSort Error");
                }
            }
        }
    }

原 码:

    public class QuickSorter
    {
        public delegate int CompareDelegate(int IdxA, int IdxB);

        public delegate void SwapDelegate(int IdxA, int IdxB);

        private CompareDelegate Comparer;

        private SwapDelegate Swaper;

        public int QuickSort(int LBound, int UBound, CompareDelegate Comparer, SwapDelegate Swaper)
        {
            this.Comparer = Comparer;
            this.Swaper = Swaper;

            QuickSort(LBound, UBound);

            return 1;
        }

        private int QuickSort(int LBound, int UBound)
        {
            if (UBound - LBound < 1) return 0;

            int ForwardPointr = LBound, BackwardPointer = UBound + 1;

            //注:以第一个元素为参考

            while (ForwardPointr < BackwardPointer)
            {
                //从前往找第一个大于参考的数
                while (++ForwardPointr < BackwardPointer && Comparer(LBound, ForwardPointr) >= 0) ;

                //从后往找第一个小于等于参考的数
                while (--BackwardPointer > ForwardPointr && Comparer(LBound, BackwardPointer) < 0) ;

                //如果找到,则交换值
                if (ForwardPointr < BackwardPointer) Swaper(BackwardPointer, ForwardPointr);
            }

            //将参考值换到中间
            Swaper(LBound, --ForwardPointr);

            QuickSort(LBound, ForwardPointr - 1);
            QuickSort(ForwardPointr + 1, UBound);

            return 1;
        }
    }
原文地址:https://www.cnblogs.com/yedaoq/p/1691401.html