lyh916

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

0.简介

快速排序是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。如果能通过两个(不相邻)记录的一次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序

 

1.算法思想

在待排序的n个记录中任取一个记录(通常取第一个记录)作为枢轴,设其关键字为pivotkey。经过一趟排序后,把所有关键字小于pivotkey的记录交换到前面,把所有关键字大于pivotkey的记录交换到后面,结果将待排序记录分为两个子表,最后将枢轴放置在分界处的位置。然后,分别对左右子表重复上述过程,直至每一个子表只有一个记录时,排序完成

其中,一趟快速排序的具体做法如下:

a.设两个指针low和high,初始时分别指向表的下界和上界,设枢轴记录的关键字pivotkey(第一趟时,low=1;high=L.length)

b.从表的最右侧位置,依次向左搜索找到第一个关键字小于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若high所指记录的关键字大于等于pivotkey,则向左移动指针high(执行操作--high);否则将high所指记录与枢轴记录交换

c.再从表的最左侧位置,依次向右搜索找到第一个关键字大于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若low所指记录的关键字小于等于pivotkey,则向右移动指针low(执行操作++low);否则将low所指记录与枢轴记录交换

d.重复b和c,直至low和high相等为止。此时low和high的位置即为枢轴在此趟排序的最终位置,原表被分成两个子表

在上述过程中,记录的交换都是与枢轴之间发生,每次交换都要移动3次记录,可以先将枢轴记录暂存在r[0]的位置上,排序过程中只移动要与枢轴交换的记录,即只做r[low]或r[high]的单向移动,直至一趟排序结束后再将枢轴记录移至正确位置上

 

例:

起始:{3,4,5,1,2}

第一趟排序过程:

经过一趟排序后,确定了枢轴"3"的位置,同时分出[2,1]和[5,4]这两个子表,左子表均小于枢轴,右子表均大于枢轴,然后对左右子表进行递归操作即可

 

2.算法实现

 1 using System.Collections.Generic;
 2 
 3 public class TestQuickSort : TestSort
 4 {
 5     void Start()
 6     {
 7         List<int> list = new List<int> { 49, 38, 65, 97, 76, 13, 27, 49 };
 8         Print(list, "排序前:");
 9         QuickSort(list);
10         Print(list, "排序后:");
11     }
12 
13     //进行一趟排序,返回枢轴位置
14     int Partition(List<int> list, int low, int high)
15     {
16         int pivotkey = list[low];//用子表的第一个记录做枢轴记录
17         while (low < high)//从表的两端交替地向中间扫描
18         {
19             while (low < high && list[high] >= pivotkey)
20             {
21                 high--;
22             }
23             list[low] = list[high];//将比枢轴记录小的移到低端
24 
25             while (low < high && list[low] <= pivotkey)
26             {
27                 low++;
28             }
29             list[high] = list[low];//将比枢轴记录大的移到低端
30         }
31         list[low] = pivotkey;//记录枢轴
32         return low;
33     }
34 
35     void QSort(List<int> list, int low, int high)
36     {
37         if (low < high)
38         {
39             int pivotkeyPos = Partition(list, low, high);//将list一分为二,pivotkeyPos是枢轴位置
40             QSort(list, low, pivotkeyPos - 1);//对左子表递归排序
41             QSort(list, pivotkeyPos + 1, high);//对右子表递归排序
42         }
43     }
44 
45     void QuickSort(List<int> list)
46     {
47         QSort(list, 0, list.Count - 1);
48     }
49 }

結果:

 

3.算法分析

a.时间复杂度

从快速排序算法的递归数可知,快速排序的趟数取决于递归树的深度

平均情况:O(nlog2n),优于冒泡排序的O(n2)

b.空间复杂度

快速排序是递归的,执行时需要有一个栈来存放相应的数据。最大递归调用次数与递归数的深度一致,所以最好情况下的空间复杂度为O(log2n),最坏情况下为O(n)

 

4.算法特点

a.是不稳定排序

b.当初始记录无序,n较大时,此算法宜采用

posted on 2020-03-07 23:03  艰苦奋斗中  阅读(807)  评论(0编辑  收藏  举报