【快速排序】快速排序与数学归纳法

      public delegate bool CompareDelegate(HPoint2d point0, HPoint2d point1);

      public void QuikSort(List<HPoint2d> lstPoint, int indexS, int indexE, CompareDelegate 
         compare)
      {
         if (indexE <= indexS)
            return;

         int indexP = Partition(lstPoint, indexS, indexE, compare);
         QuikSort(lstPoint, indexS, indexP - 1, compare);
         QuikSort(lstPoint, indexP + 1, indexE, compare);
      }

      public int Partition(List<HPoint2d> lstPoint, int indexS, int indexE, CompareDelegate 
         compare)
      {
         HPoint2d ptBase = lstPoint[indexE];
         int i = indexS - 1;
         for(int j = indexS; j < indexE; j++)
         {
            if(compare(lstPoint[j], ptBase))
            {
               i++;
               var ptTemp = lstPoint[i];
               lstPoint[i] = lstPoint[j];
               lstPoint[j] = ptTemp;
            }
         }

         var ptTemp2 = lstPoint[i + 1];
         lstPoint[i + 1] = lstPoint[indexE];
         lstPoint[indexE] = ptTemp2;

         return i + 1;
      }

(1)对于一个序列,首先将各元素与最后一个元素进行比较,并将较小的元素放到其左边,较大元素放到其右边;

(2)得到两个子序列,对每个子序列按上述方法处理,递归处理;

(3)即得到原位置已排序号的序列。

关键位置在Partition方法,该方法运用了归纳法,

1)初始条件:int i = indexS - 1;int j = indexS;

i及其前的所有元素都小于最后一个元素ptBase;i与j之间([i,j))的所有元素都大于ptBase

2)若j<ptBase,说明比ptBase小的元素增加1,即i++,并将i与j元素互换;----情况1

若j>ptBase,不作处理;----情况2

然后j++进行下一次判断。

注意i与j元素互换的一步是为了处理当出现情况2后再次出现情况1时,比ptBase小的元素应该+1(i++),为了保证处理后仍然满足i及其前的所有元素都小于最后一个元素ptBase;i与j之间([i,j))的所有元素都大于ptBase需将i位置元素(大于ptBase)与j位置元素(小于ptBase)互换。

3)经过第二步处理后,依然满足i及其前的所有元素都小于最后一个元素ptBase;i与j之间([i,j))的所有元素都大于ptBase这一条件;

4)循环第二步直到j==indexEnd-1;每次处理后都满足上述红色字体所注条件;

结束循环时,对于该序列,i及其前的所有元素都小于最后一个元素ptBase;i与j之间([i,j))的所有元素都大于ptBase,此时只需要将i+1位置元素(大于ptBase)与ptBase位置互换后就满足该序列ptBase(i+1位置)之前的所有元素小于等于ptBase,之后的所有元素大于ptBase,

这样一个序列已经划分为两个子序列,对每个子序列按上述递归得到在原位置排序好的序列。

如果将判断依据作为参数传入快排方法,就会灵活很多。

猜你喜欢

转载自blog.csdn.net/baidu_38621657/article/details/88368892