快速排序

    技术2025-01-11  12

       快速排序是对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据段变成有序序列。

      过程: 每趟调用都要选择一个基准元素,将待处理段按这个基准数据进行划分,即左边的元素都小于等于基准元素,而右边都大于等与基准元素. 针对下面的算法,注意扫描过程是右->左->右->左....这样交替进行的, 算法首先把基准元素保存到temp中,这样数组就空出一个位置了(i 指向的位置) ,接着从右边开始扫描寻找比temp小的元素,找到后将元素覆盖到 i 指向的位置(i 中的元素已经放到temp中了),接着换左边开始扫描(i中元素是有效数据,这时j 指向的空间是交换空间),左边扫描时逐1增加i的数值,直到找到一个Array[i]>temp,将array[i]保存到arra[j]中,j 指向的空间是交换空间,接着再换右边开始扫描,如果到i=j都没找到符合条件的元素就表示i(i=j)位置就是temp元素应该存放的位置了,上面过程可以看到i或j其中必然有一个指向交换空间(元素已经被移动,里面的内容没有意义了,在C#的引用类型中这个就是一个指针数据)而当i=j时可以放心的执行array[i]=temp 或array[j]=temp 操作,将基准元素放会到数组排序后对应的位置.

     关键点: 选择基准元素是随机的(一般是第一个)因此这个元素的位置是不确定的,(不要老以为它应该放到数组的中间位置),而上面的操作实质上都是围绕给基准元素找到一个合适位置进行的,执行上面描述的过程后, 只要基准元素找到位置则可. 比方数组的第一个元素是23,而23是数组的最小元素,那么根据上面过程执行后会发现最后i=j=0, 那么array[i]=temp 将把23放回array[0]位置.这样继续递归时左边的递归调用直接返回,而右边则是少一个元素的QuickSort.

     说明: 快速排序是不稳定排序,即两个等价元素其先后(左右)位置与排序前不统一,比方 x1,.....x2 ,排序后有可能是 ...x2,x1...,这样的形式. C#代码实现

    -----------------------------------------

     public class QuickSort     {         public static void Sort(T[] array, IComparer comparer)         {             Sort(array, 0, array.Length - 1, comparer);         }         ///

            /// 注意这里注意扫描过程的处理         /// 元素移动后,那么它原来的位置就用来当临时空间来使用了         /// 而i或j其中一个始终指向这个临时空间,当i=j时,表示扫描结束         /// 最后array[i]=temp,将选择的中间元素放回到数组里(排序后对应的位置)         ///         ///         ///         ///         ///         private static void Sort(T[] array, int L, int h, IComparer comparer)         {             T temp;             int i, j;             if (L < h)//至少有2个元素             {                //选择第一个元素为基准元素,从右开始扫描                 temp = array[L]; i = L; j = h;                 while (i < j)                 {                     //选择 array[j] < temp的元素,将其移动到前面 i 指向的位置                     //而移动后的空间可空出来做下次交换使用,这时j为这个空间的下标                     while (i < j && comparer.Compare(temp, array[j]) <= 0) j--;                     //i                     if (i < j) array[i] = array[j];                     //从左边开始扫描大于temp的元素                     while (i < j && comparer.Compare( array[i],temp) <= 0) i++;                     //i< j表示找到一个大与                     if (i < j) array[j] = array[i];                 }                 //这里有i=j;temp元素找到自己的位置了,                 //左变的都比temp小,右边的都比temp大(或者等于)                 array[i] = temp;

                    Sort(array, L, i - 1, comparer);//完成左边                 Sort(array, i + 1, h, comparer);//完成右边

                }                     }     }

    ------------------------------

     另外在.net2.0中的很多集合类其中的Sort方法使用的都是快速度排序实现的,因此进行集合排序时不需要自己专门实现这么个排序方法. 从Reflector摘录的部分代码

    ---------------------------------

       private void QuickSort (T[] keys, TValue[] values, int left, int right, IComparer comparer)     {         do         {             int a = left;             int b = right;             int num3 = a + ((b - a) >> 1); //中间值下标,等价于 a+ (b-a)/2             this.SwapIfGreaterWithItems (keys, values, comparer, a, num3);             this.SwapIfGreaterWithItems (keys, values, comparer, a, b);             this.SwapIfGreaterWithItems (keys, values, comparer, num3, b);             T y = keys[num3];             .............................  这里在排序前先进行"三者取中",即比较这3个元素的大小取中间值做为基准,另外上面类的扫描过程不是交替进行的,而是两边同时扫描(可能找到2个后互换),具体参考Reflector后的代码,下面给出链接中的算法分析有"三者取中"的说明.  参考 快速排序算法原理与实现 算法分析(网站名称: 数据结构)

    最新回复(0)