C#快速排序算法

今天重温了下排序算法,包括冒泡排序法和直接排序法,这些都比较简单,只是快速排序法比较难,于是重点研究了下。

  先说一说原理:快速排序法是采用递归的方式对待排序的数列进行若干次的操作,每次操作使得被操作的数列部分以某个元素为分界值分成两部分,一部分小于该分界值,另一部分大于该分界值.该分界值一般被称为”枢轴”. 一般先以左边第一个数作为分界值,将数列按该分界值分成左右两部分,左边部分小于该分界值,右边部分大于该分界值,然后再对左右两部分做重复的操作,直到最后完成排序。

以数列 14,11,25,37,9,28 为例,详细描述执行一趟快速排序的算法:

1.选择待排序数列的枢轴,一般以数列的首元素作为枢轴.此数列中,我们选择首元素14作为枢轴,nPivot = 14.

2.设定两个指针 i 和 j ,分别指向数列的首元素和尾元素. i 指向首元素14, j 指向尾元素28.示意图如下:
这里写图片描述

3.向前移动尾指针 j ,使其指向从数列尾部算起首个小于枢轴(即14)的元素,并将该元素置换到头指针 i 指向的位置._nArray[i] =_nArray[j].示意图如下:
这里写图片描述

首次执行该操作时 i 指针指向处的值实际上就是枢轴的值,此处的操作可以理解为 i 指针指向处的值已在之前被置换到枢轴中,此时, i 指向处已经是一个空位,在此时用找到的小于枢轴的元素填在此处.

4,向后移动头指针 i ,使其指向从数列头部算起首个大于枢轴(即14)的元素,并将该元素置换到尾指针 j 指向的位置._nArray[j] =_nArray[i].示意图如下:
这里写图片描述

此处同样可以理解为 j 指针指向处的值已在上一步操作中置换了出去. j 处已是一个空位.

5,如此重复执行步骤3和步骤4,直至 i==j 时结束该循环.

6,退出了该循环后, i 与 j 必定指向同一位置.在该位置的前部元素,其值均小于枢轴.而在该位置的后部元素,其值均大于枢轴.显而易见,此时 i 和 j 同时指向的位置就应该是枢轴的”新家”._nArray[i]=nPivot.如下图:
这里写图片描述

至此,一趟排序结束.待排序数列的首元素将该数列分成了比其小和比其大的两部分.如下图:
这里写图片描述

接着,我们对这一大一小两部分子数列执行相同的排序操作.

如此”递归”,直至对整个数列完成排序操作.

以下是c#实现代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 快速排序
{
    using System;
    public static class Program
    {
        public static void Main()
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            const int z = 10000000;
            //随机生成一千万个数。
            int[] a = new int[z];
            Random random = new Random();
            for (int i = 0; i < z; i++)
            {
                a[i] = random.Next(0, z);
            }
            watch.Start();//计时器开始。
            QuickSort(a, 0, z - 1);
            watch.Stop();//计时器结束。
            for (int i = z - 1000; i < z; i++)
            {
                Console.WriteLine(a[i]);
            }
            string time = watch.ElapsedMilliseconds.ToString();
            Console.Write("排序所用时间 :" + " " + time + " ms");
            Console.Write("\r\n");
            Console.ReadKey();
        }
        private static void QuickSort(int[] a, int low, int high)
        {
            if (low >= high)
            {
                return;
            }
            int pivot = QuickSortOnce(a, low, high);//输出每一次排序。

            //对枢轴左端进行排序。
            QuickSort(a, low, pivot - 1);
            //对枢轴右端进行排序。
            QuickSort(a, pivot + 1, high);
        }
        private static int QuickSortOnce(int[] a, int low, int high)
        {
            //将首个元素作为枢轴。
            int pivot = a[low];
            int i = low, j = high;
            while (i < j)
            {
                //从右往左,寻找首个小于povit的元素。
                while (a[j] >= pivot && i < j)
                {
                    j--;
                }
                //执行到此,j一定指向从右端起首个小于或等于povit的元素。执行替换。
                a[i] = a[j];
                //从左往右,寻找首个大于povit的元素。
                while (a[i] <= pivot && i < j)
                {
                    i++;
                }
                ////执行到此,j一定指向从右端起首个大于或等于povit的元素。执行替换。
                a[j] = a[i];
            }
            //退出while循环,执行至此,必定是i==j的情况。i(或j)指向的既是枢轴的位置,定位该趟排序的枢轴并将该位置返回。
            a[i] = pivot;
            return i;






        }

    }
}

猜你喜欢

转载自blog.csdn.net/qq_43023809/article/details/82690171