• [Unity算法]交换排序(二):快速排序


    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较大时,此算法宜采用

  • 相关阅读:
    select,radio,checkbox的美化
    BBMASTER 博客
    thymeleaf教程
    Spring Boot入门01
    thymeleaf
    [转]Eclipse中10个最有用的快捷键组合
    SpringMVC实现文件上传
    Maven_项目管理利器入门
    [转]centos6.5安装mysql
    YOUNG博客项目设计书_v01.00_账号管理模块
  • 原文地址:https://www.cnblogs.com/lyh916/p/12439133.html
Copyright © 2020-2023  润新知