zoukankan      html  css  js  c++  java
  • 快速排序——PowerShell版

    继续读啊哈磊算法有感系列,继续升华。上一篇是冒泡排序,在结尾总结了一下冒泡排序的缺点——时间复杂度O(N*N)太大。这一篇来说一下快速排序,快速排序可以在多数情况下克服冒泡排序的缺点(最坏的情况下和冒泡排序的时间复杂度一样)。下面我们先来说说快速排序的思想与过程,与上一篇从过程到思想的思考方式不同,这一次我们的思考过程是从思想到过程——

    快速排序的思想:

    利用二分的思想,先在待排序子数组中选定一个基准数(作为中间值)、一个左初始位(待排序子数组的左端点位。若对整个数组进行排序,则左端点位为数组的0索引位),一个右初始位(待排序子数组的右端点位。若对整个数组进行排序,则右端点位为数组的length-1处索引位),然后找到一个位置,该位置左侧的数均小于基准数,右侧的数均大于基准数。在此基础上,对待排序子数组进行二分,分别为待排序子数组中基准数以左,左初始位以右的孙子数组1;和待排序子数组中基准数以右,右初始位以左的孙子数组2。之后进行递归,将孙子数组1和2分别作为待排序子数组进行同上排序。

    快速排序的过程(与上一篇中思想就是对过程的抽象与总结相反,过程就是对思想的具体与落实):

    1、选定待排序子数组及其基准数、左初始位、右初始位(若左初始位小于右初始位则继续,否则停止);

    2、找到基准数的交换位置,在左初始位和右初始位分别安排一名哨兵,先是右哨兵向左走,直到找到第一个比基准数小的数为止;然后是左哨兵向右走,直到找到第一个比基准数大的数为止。交换左右哨兵位置处的数值,然后哨兵继续前行(先右后左),继续交换,直到左右哨兵相遇前,停止。至此第一轮排序结束了,左哨兵以左都小于等于基准数,右哨兵以右都大于等于基准数;

    3、交换左哨兵和基准数的数值,至此基准数以左均小于等于基准数,基准数以右都大于等于基准数;

    4、以基准数所在的位置对待排序子数组进行二分,分为孙子数组1和2;

    5、对孙子数组1和2进行递归,回到第一步,孙子数组1的左初始位为待排序子数组的左初始位并依然以左初始位的数为新的基准数、右初始位为基准数位-1,孙子数组2的左初始位为基准数位+1并以左初始位的数位新的基准数、右初始位为待排序子数组的右初始位。

    等到孙子数组2的左初始位和孙子数组1的右初始位相遇时,这场排序就结束了。整个待排序子数组将会按照从小到大进行排序。

    接下来我们将具体的过程转换为代码:

    #Exchange the two value.
    function ExchangeValue($i,$j, $studentScore, $studentName)
    {
        #Exchange the score.
        $s = $studentScore[$i] 
        $studentScore[$i] = $studentScore[$j]
        $studentScore[$j] = $s
        #Exchange the name.
        $n = $studentName[$i] 
        $studentName[$i] = $studentName[$j]
        $studentName[$j] = $n
    }
    function SortScores($left, $right, $studentScore, $studentName)
    {
        if($left -le $right)
        {
            #Sort begin.
            #The $left is base number, the $left and $right also represents the location of the sentries' start points.  
            $i = $left
            $j = $right
            #The right sentry must go first every time while the sentries not meet each other.
            while($i -ne $j)
            {
                while(($studentScore[$j] -ge $studentScore[$left]) -and ($j -gt $i))
                {
                    $j--
                }
                #And then the left one.
                while(($studentScore[$i] -le $studentScore[$left]) -and ($i -lt $j))
                {
                    $i++
                }
                #If the left entry doesn't meet the right entry, exchange the left and right number.
                If($i -lt $j)
                {
                    ExchangeValue $i $j $studentScore $studentName
                }
            }
            #Exchange the value from the locations of the left entry and the base number.
            ExchangeValue $left $i $studentScore $studentName
            #Now "$i" is the new location of the base number.
            #Sort the new left part.
            $newRight = $i-1
            $newLeft = $i+1
            SortScores $left $newRight $studentScore $studentName
            SortScores $newLeft $right $studentScore $studentName
        }
    }
    function PrintSortedScores($count, $studentScore, $studentName){
        #Print the sorted result.
        Write-Host "Below is the sorted result:"
        for($i=0;$i -le $count-1;$i++)
        {
            $j=$i+1
            $tip = "NO."+$j+":"+$studentName[$i]+",score:"+$studentScore[$i]
            Write-Host $tip -ForegroundColor Green
        }
    }
    #This is the entry of this program.
    #Collect the students' scores.
    $count = Read-Host "Enter the amout number of the students"
    #Convert to int type.
    $count = [int]$count
    $studentName = New-Object System.Collections.ArrayList
    $studentScore = New-Object System.Collections.ArrayList
    for($i=1;$i -le $count;$i++)
    {
        $name = Read-Host "Enter the name"
        $score= Read-Host "Enter the score"
        #Convert to int type.
        $score = [float]$score
        $studentName.Add($name)
        $studentScore.Add($score)
    }
    $leftNum = 0
    $rightNum = $count - 1
    SortScores $leftNum $rightNum $studentScore $studentName
    PrintSortedScores $count $studentScore $studentName

    函数SortScores是快速排序算法的核心,其中关键的判断我用橙色高亮了出来。

    在PowerShell中运行这段代码,并输入一些测试数据,结果如下:

    冒泡排序的交换距离是相邻的两个元素,而快速排序中左右哨兵并不是相邻的,所以交换的两个元素也不是相邻的,最坏的情况,左右哨兵碰头的时候交换才会交换相邻的两个元素。如果每次都是最坏的情况(每次都是左右哨兵相邻才交换),那快速排序的时间复杂度和冒泡排序是一样的。但只要不是最坏的情况,快速排序的时间复杂度都要小于冒泡排序,它的平均时间复杂度是O(NlogN)。

  • 相关阅读:
    面试题来积累自己
    基于php基础语言编写的小程序之计算器
    配置apache的虚拟机+软件下载
    执行表空间使用率SQL突然变慢问题分析
    DM-建库选项-字符串比较大小写敏感-测试
    OGG再次遇到虚拟列无法处理,导致进程abend二
    OGG应用进程abend报错无法insert虚拟列
    Oracle Asm Failgroup测试学习
    OGG复制进程报错,存在update set 主键列 is null
    测试:OGG初始化同步表,源端抽取进程scn<源端事务的start_scn时,这个变化是否会同步到目标库中?
  • 原文地址:https://www.cnblogs.com/LanTianYou/p/4853515.html
Copyright © 2011-2022 走看看