排序---快速排序

1、概念html

快速排序由C.A.R.Hoare在1962年提出,是冒泡排序的一种改进。其基本思想为:经过一趟排序将待排序数据分割成独立的两部分,其中一部分的全部值都比另外一部分的全部值都小,而后再对分割的两部分分别进行快速排序,整个过程能够递归进行,最终全部数据变为有序序列。算法

2、算法要点数组

假设待排序数组为a[0], a[1],…a[n-1],快速排序步骤如下:dom

一、初始化两个变量i、j,刚开始i = 1,j=n-1。oop

二、将第一个元素a[0]做为基准数。ui

三、从i开始向后搜索,找到第一个大于基准数的元素a[i]。spa

四、从j开始向前搜索,找到第一个小于等于基准数的元素a[j]。code

五、将a[i]与a[j]互换。htm

六、重复3到5步骤,直到i = j + 1,此时,j指向的元素是最后一个(从左边算起)小于等于中轴的元素,而后将a[0]与a[j]对换。blog

七、序列被基准数分割成两个分区,前面分区所有小于等于基准数,后面分区所有大于基准数。

八、递归对分区子序列进行快速排序,最终完成整个排序工做。

每趟快速排序的核心工做是:

选一个元素做为基准数,而后将全部比它小的数都放到它前面,大于它的数都放在它后面。

3、算法实现

实现一:

 1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace QuickSort
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             QuickSortUnitTest(13);
11 
12         }
13         private static void QuickSort(List<int>dataList, int left, int right)
14         {
15             if(left < right)//递归的边界条件,当left等于right时,元素个数为1个
16                 {
17                 int pivot = dataList[left];//最左边的元素做为中轴
18                 int i = left + 1;
19                 int j = right;
20                 int tmp = 0;
21                 //当i == j时,i和j同时指向的元素尚未与中轴元素判断,
22                 //小于等于中轴元素,i++,大于中轴元素j--,
23                 //当循环结束时,必定有i = j + 1, 且i指向的元素大于中轴,j指向的元素小于等于中轴
24                 while (i <= j)
25                 {
26                     while(i <= j && dataList[i] <= pivot)//从前向后找到第一个大于pivot的元素
27                     {
28                         i++;
29 
30                     }
31                     while(i <= j && dataList[j] > pivot)
32                     {
33                         j--;
34 
35                     }
36                     if(i < j)
37                     {
38                         tmp = dataList[i];
39                         dataList[i] = dataList[j];
40                         dataList[j] = tmp;
41                     }                    
42                 }
43                 //当循环结束时,j指向的元素是最后一个(从左边算起)小于等于中轴的元素
44                 //将中轴元素和j所指的元素互换
45                 tmp = dataList[left];
46                 dataList[left] = dataList[j];
47                 dataList[j] = tmp;
48                 Console.WriteLine();
49                 foreach (var item in dataList)
50                 {
51                     Console.Write($" {item} ");
52                 }
53                 Console.WriteLine();
54                 QuickSort(dataList, left, j - 1);
55                 QuickSort(dataList, j + 1  , right);
56             }
57         }
58         private static void QuickSortUnitTest(int loopNum)
59         {
60             Random random = new Random();
61             List<int> dataList = new List<int>();
62             for (int i = 0; i < loopNum; i++)
63             {
64                 dataList.Add(random.Next(100));
65             }
66             Console.Write("Original data:");
67             foreach(var item in dataList)
68             {
69                 Console.Write($" {item} ");
70             }
71 
72             QuickSort(dataList, 0, dataList.Count - 1);
73             Console.Write("Quick sorted data:");
74 
75             foreach (var item in dataList)
76             {
77                 Console.Write($" {item} ");
78             }
79             Console.WriteLine();
80         }
81     }
82 }

 实现二:

基本思想:“挖坑填坑”

使用两个变量i和j分别指向最左边和最右边的元素,咱们将首元素做为中轴,并复制到变量pivot中,这时咱们能够将首元素i所在的位置当作一个坑,咱们从j的位置从右向左扫描,找一个小于等于中轴

的元素A[j],来填补A[i]这个坑,填补完成后,拿去填坑的元素所在的位置j又能够看作一个坑,这时咱们在以i的位置从前日后找一个大于中轴的元素来填补A[j]这个新的坑,如此往复,直到

i和j相遇(i == j,此时i和j指向同一个坑)。

最后咱们将中轴元素放到这个坑中。而后,咱们按照相同的方法分别对左右两个数组执行相同的操做。

private static void QuickSort2(List<int>dataList, int left, int right)
        {
            if(left < right)
            {
                //最左边的元素做为中轴复制到pivot,这时最左边的元素能够看作一个坑
                int pivot = dataList[left];
                //注意这里 i = L,而不是 i = L+1, 由于i表明坑的位置,当前坑的位置位于最左边
                int i = left;
                int j = right;
                while(i < j)
                {
                    //下面面两个循环的位置不能颠倒,由于第一次坑的位置在最左边
                    while (i < j && dataList[j] > pivot)
                    {
                        j--;
                    }
                    //填A[i]这个坑,填完后A[j]是个坑

                    //注意不能是A[i++] = A[j],当因i==j时跳出上面的循环时

                    //坑为i和j共同指向的位置,执行A[i++] = A[j],会致使i比j大1,

                    //但此时i并不能表示坑的位置 
                    dataList[i] = dataList[j];
                    while(i < j && dataList[i] <= pivot)
                    {
                        i++;
                    }
                    dataList[j] = dataList[i];
                }
                //循环结束后i和j相等,都指向坑的位置,将中轴填入到这个位置
                dataList[i] = pivot;
                QuickSort2(dataList, left, i - 1);
                QuickSort2(dataList, i + 1, right);
               

            }
        }

 更多方法请参考:

http://www.javashuo.com/article/p-qqxterok-gm.html

相关文章
相关标签/搜索