排序算法——快速排序(高速排序)的代码解读

此笔记仅作本人学习、复习与思考用。(代码参考网络)

规定arr[] = {49, 38, 65, 97, 76, 13, 27}

算法步骤:

1,选择基点,规定基点 = index(通常选择数组第一个数)

2,设置left,right(left代表数组最左即arr[0],right代表数组最右即arr[arr.Length - 1],设置left和right是为了向后向前遍历比较和基点的大小)

3,arr[left] 和 index进行比较,如果arr[left] 大于 index 则放到后面 否则left++ 一直往后找直到找到大于index的值 arr[right] 和 index 进行比较 ,如果arr[right] 小于 index 则放到前面 否则right-- 一直往前找直到找到小于index的值(这样规定的原因取决于这个数组是采取降序排序还是升序排序,现在介绍的升序排序)

4,将设置的基点index 放入当前的数组中间

5,重复 2 ,3,4 步骤直到 left == right

代码示例:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace 排序__高速排序
 8 {
 9     class Program
10     {
11         public static int[] s = { 49, 38, 65, 97, 76, 13, 27 };
12         static void Main(string[] args)
13         {
14             FastSort(s, 0, s.Length - 1);
15             Console.ReadKey();
16         }
17        
18         private static int SortUnit(int []arr,int left,int right)
19         {
20             int i = left, j = right;
21             int index = arr[left];
22             while(left<right)
23             {
24                 while (left < right && arr[right] > index) right--;
25                 arr[left] = arr[right];
26                 while (left < right && arr[left] <= index) left++;      //   修改
27                 arr[right] = arr[left];
28                 
29             }
30             arr[left] = index;
31             foreach (var item in arr)
32             {
33                 Console.Write("{0}       ", item);
34             }
35             Console.Write("
");
36             return left;
37         }
38 
39         public static void FastSort(int []s,int left,int right)
40         {
41             if (left >= right) return;
42             int index = SortUnit(s, left, right);
43             FastSort(s, left, index - 1);
44             FastSort(s, index + 1, right);
45         }
46     }
47 }

完成排序的片段:

private static int SortUnit(int []arr,int left,int right)
        {
            int i = left, j = right;
            int index = arr[left];
            while(left<right)           //  @1
            {
                while (left < right && arr[right] > index) right--;
                arr[left] = arr[right];
                while (left < right && arr[left] < index) left++;
                arr[right] = arr[left];
                
            }
            arr[left] = index;                           // @2
            foreach (var item in arr)
            {
                Console.Write("{0}       ", item);
            }
            Console.Write("
");
            return left;            //@4
        }

        public static void FastSort(int []s,int left,int right)   //@5
        {
            if (left >= right) return;
            int index = SortUnit(s, left, right);
            FastSort(s, left, index - 1);
            FastSort(s, index + 1, right);
        }

代码解读:

@1 :该循环是将该数组进行一次排序,排序方式(此处说升序)是 首先从后往前找如果碰到小于index就放到前面,如果不存在这样的数,那么直到left和right相同则停止遍历,从前往后的比较也一样(此处说明一下为什么是先从后往前比较而不是先从前往后比较,这个和选择基点index有关系,因为该例子选择的是数组的第一个元素作为基点index,所以在比较后交换的时候,index就有了保存而不是被覆盖掉,如果要先从前往后比较,那么选择的基点就必须是最后一个元素,这样在arr[right] = arr[left] 赋值的时候,就不会覆盖掉arr[right]原先的值,因为已经被保存

@2:比较且置换完毕之后,选择将基点作为该数组的中间值,且因为此时left = right 所以 直接返回 left 以便为了切割数组(快速排序是通过分治法即递归来完成排序的,所以需要将原先的数组一分为二,左半边数组重复排序步骤,右半边数组重复排序步骤,直到最终被切割成每个数组的元素只有1个时排序结束)

@5:递归结束条件就是left = right 即 该数组的长度为1 即 原数组切割完毕,index 表示使的原数组进行一次排序,获得@4的值 更好的重复递归步骤

PS:这个算法是比较不稳定的,据说有优化的方法,可以使得该方法出现最坏的情况的几率下降,最坏情况是指时间复杂度为O(n2)的情况,有空再研究

后期优化:在代码标注修改处,从原来的 < 修改成现在的 <= ,原因是当需要排序的数组出现相同的数字的时候,可能会出现死循环的情况的!