快速排序

    技术2025-05-01  11

    一、快速排序

      【分治法】快速排序在每一轮挑选一个基准元素,并让其他比他大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解为两个部分。

    【基元素选择】①最简单的方式是选择数列的第一个元素,但是在极端情况下快速排序需要进行n轮,时间复杂度为【】

                             ②为避免极端情况发生,可以随机选择一个元素作为基准元素,并且让基准元素和数列首元素交换位置。

    二、快速排序步骤

    ①选定了基元素后,就把其他元素中小于基元素的都交换到基元素一边,大于基元素的都交换到基元素的另一边。

    ②双边循环法:《1》选定基元素后,并且设置两个索引left和right,指向数列的最左和最右两个元素。

                             《2》接下来进行第一次循环,从right索引开始,让索引指向的元素和基元素做比较,如果>=基元素,则索引左移动;如果索引<基元素,则right索引停止移动;切换到Left索引移动。

                             《3》当left索引移动时,让left索引指向的元素和基元素作比较,如果<=基元素,则left索引右移动,如果>基元素,则停止left移动,切换为right索引移动。

                             《4》如此反复。

    ③单边循环法:《1》只从数组的一边对元素进行遍历和交换

                             《2》如果遍历到的元素>基元素,则继续往后遍历

                              《3》如果遍历到的元素<基元素,则把数组第一个索引指定为mark,然后把mark索引右移动1位,因为<基元素的区域边界增大了1;然后把最新遍历到的元素和mark索引所在的位置的元素交换位置,因为最新遍历的元素归属小于基元素区域。

    三、快速排序核心

    /*** * Title: "算法" 项目 * 主题 : 快速排序 * Description: * 功能 : * Date: 2020-07-04 * Version: 1.2 * Author: Coffee * Modify Recoder: */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Kernal { class QuickSort { /// <summary> /// 分治(双边循环法) /// </summary> /// <param name="array">待交换数组</param> /// <param name="startIndex">起始下标</param> /// <param name="endIndex">结束下标</param> /// <returns></returns> public static void DoubleLoop(int[] array, int startIndex, int endIndex) { //递归结束条件 if (startIndex >= endIndex) { return; } //得到基准元素位置 int pivotIndex = ParitionDouble(array, startIndex, endIndex); //根据基准元素,分成两部分进行递归排序 DoubleLoop(array, startIndex, pivotIndex - 1); DoubleLoop(array, pivotIndex + 1, endIndex); } /// <summary> /// 分治(单边循环法) /// </summary> /// <param name="array">待交换数组</param> /// <param name="startIndex">起始下标</param> /// <param name="endIndex">结束下标</param> /// <returns></returns> public static void SingleLoop(int[] array, int startIndex, int endIndex) { //递归结束条件 if (startIndex>=endIndex) { return; } //得到基准元素 int pivotIndex = ParitionSingle(array, startIndex, endIndex); //根据基准元素,分成两部分进行递归排序 SingleLoop(array,startIndex,pivotIndex-1); SingleLoop(array,pivotIndex+1,endIndex); } /// <summary> /// 分治(双边循环法) /// </summary> /// <param name="array">待交换数组</param> /// <param name="startIndex">起始下标</param> /// <param name="endIndex">结束下标</param> /// <returns></returns> private static int ParitionDouble(int[] array,int startIndex,int endIndex) { //取第1个位置(也可以选择随机位置)的元素作为基准元素 int pivot = array[startIndex]; int left = startIndex; int right = endIndex; while (left!=right) { //控制right索引比较并左移 while (left<right && array[right]>pivot) { right--; } //控制left索引比较并右移 while (left<right && array[left]<=pivot) { left++; } //交换left和right索引所指向的元素 if (left<right) { int tmp = array[left]; array[left] = array[right]; array[right] = tmp; } } //pivot和索引重合点交换 array[startIndex] = array[left]; array[left]=pivot; return left; } /// <summary> /// 分治(单边循环法) /// </summary> /// <param name="array">待交换数组</param> /// <param name="startIndex">起始下标</param> /// <param name="endIndex">结束下标</param> /// <returns></returns> private static int ParitionSingle(int[] array, int startIndex, int endIndex) { //取第1个位置(也可以选择随机位置)的元素作为基准元素 int pivot = array[startIndex]; int mark = startIndex; for (int i = startIndex+1; i <= endIndex; i++) { if (array[i]<pivot) { mark++; int tmp = array[mark]; array[mark] = array[i]; array[i] = tmp; } } array[startIndex] = array[mark]; array[mark] = pivot; return mark; } }//Class_end }

    四、使用方法

    ①、引用命名空间:using Kernal;

    ②、QuickSort+方法名称;

    ③、在方法中传入列表即可。

    五、示例

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Kernal; namespace CommonSort { class Program { static void Main(string[] args) { //时间计时器 Stopwatch _SW = new Stopwatch(); Console.WriteLine("原数组为:"); int[] array = {69, 25, 78, 1, 56, 24, 98, 71, 2, 6, 1, 5, 8, 9}; int[] array2 = { 69, 25, 78, 1, 56, 24, 98, 71, 2, 6, 1, 5, 8, 9 }; Display(array); Console.WriteLine("\n--------------- 分治(双边循环法)----------------------"); _SW.Start(); Console.WriteLine(" 分治(双边循环法)为:"); QuickSort.DoubleLoop(array,0,array.Length-1); Display(array); _SW.Stop(); Console.WriteLine("花费时间为:{0} 毫秒",_SW.Elapsed.TotalMilliseconds); Console.WriteLine("\n--------------- 分治(单边边循环法)----------------------"); _SW.Restart(); Console.WriteLine(" 分治(单边边循环法)为:"); QuickSort.SingleLoop(array2, 0, array2.Length - 1); Display(array2); _SW.Stop(); Console.WriteLine("花费时间为:{0} 毫秒", _SW.Elapsed.TotalMilliseconds); Console.Read(); }//Main_end //显示结果 private static void Display(int[] array) { string str = null; foreach (var item in array) { str += item + " "; } Console.WriteLine(str); } }//Class_end }

    六、结果如下

     

     

     

     

     

    Processed: 0.024, SQL: 9