代码改变世界

快速排序(QuickSort)的C#实现(采用随机化主元方式)

2011-09-11 21:14  java线程例子  阅读(302)  评论(0编辑  收藏  举报

算法代码如下:

/// <summary>
        /// 快速排序的分隔,即:对于一个指定的主元x,找到位置i,使得i的左边元素都小于等于x,右边都大于等于x.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="p"></param>
        /// <param name="q"></param>
        /// <returns></returns>
        private int QuickSortPartion(int[] A, int p, int q)
        {

            int theCount = q - p + 1;
            //只有一个元素的情况,返回-1表示不用继续分割
            if (theCount==1)
            {
               
                return -1;
            }
            //如果元素为2,则不用继续分割,只需要简单处理即可,这可以节省一些时间,但不是必须.
            if (theCount == 2)
            {
                if (A[p] > A[q])
                {
                    int tmp = A[p];
                    A[p] = A[q];
                    A[q] = tmp;
                }
                return -1;
            }
            //随机获取主元
            Random theR=new Random(10);
            int theMasterIndex = theR.Next(1, theCount);
            int theMasterP = p + theMasterIndex -1;
            //找到主元x,并与下界元素交换。
            int theX = A[theMasterP];
            A[theMasterP] = A[p];
            A[p] = theX;
            //寻找i,使得小于i位置的元素都小于等于thex,大于i位置的元素都大于thex.i初始位置为p.
            int i = p;
           //j初始位置为i+1;
            for(int j=p+1;j<=q;j++)
            {
                //如果A[j]小于等于主元,则主元位置i右移一位,A[i]与A[j]交换
                if (A[j] <= theX)
                {
                    i++;
                    int theTmp = A[j];
                    A[j] = A[i];
                    A[i] = theTmp;
                }
            }
            //做一次交换,将主元放到位置i.
            A[p] = A[i];
            A[i] = theX;
            return i;
        }
        /// <summary>
        /// 快速排序,主函数.
        /// </summary>
        /// <param name="A"></param>
        /// <param name="S"></param>
        /// <param name="E"></param>
        private void QuickSort(int[] A, int S, int E)
        {
            //先找划分位置i
            int theDivI = QuickSortPartion(A, S, E);
            //不需要划分
            if (theDivI < 0)
            {
                return;
            }
            int theP1_S = S, theP1_E = theDivI - 1;
            int theP2_S = theDivI + 1, theP2_E = E;
            //对左边递归快排
            if (theP1_E >= S)
            {
                QuickSort(A, theP1_S, theP1_E);
              
            }
            //对右边递归快排.
            if (theP2_S <= theP2_E)
            {
                QuickSort(A, theP2_S, theP2_E);
            }
        }

分治策略三步曲是:分,治,合。快排和归并排序同样采用的是分治策略,而且分治后的策略分支树都为2,但快排的优势在于,它不需要“合”,而归并排序的两个分支策略完成后,还有一个归并的过程。所以时间复杂度上归并显然不如快排。快排可以达到时间复杂度θ(n*lg(n)),归并的是θ(n*lg(n)).但快排的实际时间复杂度与其实现和输入都有关,最坏的情况,快排的时间复杂度也会达到θ(n^2),这个方面,归并排序的时间复杂度要均衡一些,与输入序列相关性不大。