快速排序

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

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

  以数列 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#实现代码

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static void Main(string[] args)
 {
     Console.WriteLine("请输入待排序数列(以\",\"分割):");
     string _s = Console.ReadLine();
     string[] _sArray = _s.Split(",".ToCharArray());
     int _nLength = _sArray.Length;
     int[] _nArray = new int[_nLength];
     for (int i = 0; i < _nLength; i++)
     {
         _nArray[i] = Convert.ToInt32(_sArray[i]);
     }
 
     var list = _nArray.ToList();
     QuickSort(list, 0, _nLength - 1);
 
     foreach (var in list)
     {
          Console.WriteLine(i.ToString());
     }
     while (true)
     {
         Thread.Sleep(10000);
     }
}
 //获取按枢轴值左右分流后枢轴的位置
 private static int Division(List<int> list, int left, int right)
 {
     while (left < right)
     {
         int num = list[left]; //将首元素作为枢轴
         if (num > list[left + 1])
         {
             list[left] = list[left + 1];
             list[left + 1] = num;
             left++;
         }
         else
         {
             int temp = list[right];
             list[right] = list[left + 1];
             list[left + 1] = temp;
             right--;
         }
         Console.WriteLine(string.Join(",", list));
     }
     Console.WriteLine("--------------\n");
     return left; //指向的此时枢轴的位置
 }
 private static void QuickSort(List<int> list, int left, int right)
 {
     if (left < right)
     {
         int i = Division(list, left, right);
         //对枢轴的左边部分进行排序
         QuickSort(list, i + 1, right);
         //对枢轴的右边部分进行排序
         QuickSort(list, left, i - 1);
     }
 }   

  原文地址:https://www.cnblogs.com/yundan/p/4022056.html

posted @ 2018-08-16 22:37  micwin  阅读(233)  评论(0编辑  收藏  举报