继续读啊哈磊算法有感系列,继续升华。上一篇是冒泡排序,在结尾总结了一下冒泡排序的缺点——时间复杂度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)。

快速排序——PowerShell版的更多相关文章

  1. Ladon内网渗透扫描器PowerShell版

    程序简介 Ladon一款用于大型网络渗透的多线程插件化综合扫描神器,含端口扫描.服务识别.网络资产.密码爆破.高危漏洞检测以及一键GetShell,支持批量A段/B段/C段以及跨网段扫描,支持URL. ...

  2. [工具]法国神器mimikatz 2.1.1 一键版 & PowerShell版

    无需任何参数,运行EXE即可自动读取Windows系统密码 EXE版需要其它功能请使用原版 (参数已写死仅读密码) 结果保存于当前目录mz.log EXE https://github.com/k8g ...

  3. 链表——PowerShell版

    链表是由一系列节点串连起来组成的,每一个节点包括数值部分和指针部分,上一节点的指针部分指向下一节点的数值部分所在的位置. 在C语言中我们有两种方式来定义链表—— 1.定义结构体:来表示链表中的节点,节 ...

  4. 栈——PowerShell版

    上一篇讲过队列(queue),队列就像是居民楼里的垃圾管道,从楼道的垃圾管道的入口处将垃圾扔进去,清洁工会从一楼垃圾管道的出口处将垃圾拿走.每一层的垃圾通道入口与一楼的垃圾管道出口之间都形成了一个队列 ...

  5. 批量备份数据库脚本(PowerShell版)

    开始 昨天备份一个数据库拿来测试,发现备份后的文件非常大.后来去检查下使用的备份脚本,原来之前的备份脚本没有压缩功能. 现把之前的备份脚本修改下,支持压缩备份,和支持仅复制备份(CopyOnly). ...

  6. 队列——PowerShell版

    继续读啊哈磊<啊哈!算法>感悟系列——队列 地铁售票处排队,先来的人先到队首先买完先走,后来的人排在队尾等候后买完后走. 想买票,必须排在队尾:买完票,只能从队首离开. 这种先进先出(Fi ...

  7. 冒泡排序——PowerShell版

    继续读啊哈磊算法有感系列.上一篇是桶排序,在结尾总结了一下简化版桶排序的缺点.这一篇来说一下冒泡排序,冒泡排序可以很好的克服桶排序的缺点.下面我们先来说说冒泡排序的过程与思想—— 冒泡排序的过程: 第 ...

  8. 桶排序——PowerShell版

    读啊哈磊的算法书有感,十一期间想要重新学一学一些基本的算法和数据结构.不想下载编程工具了,毕竟是用室友的电脑,就用PowerShell写一下吧: $scores = @(88,13,99,26,62, ...

  9. windows基线检测脚本编写指南-powershell版

    前言:   因为工作的原因,要写windows下的基线检查脚本.之前没接触过,在网上找了半天也没找到现成的,无奈只好自己研究,最后还是成功完成了工作. 在我编写之后发现windows下的基线基本就是检 ...

随机推荐

  1. ajax-原理分析

      createTime--2016年9月19日13:59:11Author:Marydon参考链接 http://blog.csdn.net/csh624366188/article/details ...

  2. 腾讯云-搭建 Python 开发环境

    搭建 Python 开发环境 准备工作 任务时间:5min ~ 10min Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.首先我们来看看系统中是否已经存在 Python ,并安装 ...

  3. Java中创建实例化对象的几种方式

    Java中创建实例化对象有哪些方式? ①最常见的创建对象方法,使用new语句创建一个对象.②通过工厂方法返回对象,例:String s =String.valueOf().(工厂方法涉及到框架)③动用 ...

  4. 一些很经典的JavaScript的问题

    1.作用域 (function() { var a = b = 5; })(); console.log(b); 输出:5 陷阱是,在函数表达式中有两个赋值,但a是用关键字var 来声明的,这意味着a ...

  5. HDUOJ-----X问题

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  6. JS数据交互:动态从数据库中获取数据填充Select

    JavaScript代码: $(document).ready(function () { getIntype(); });function getIntype(){ $.ajax({ type:&q ...

  7. JavaScript 中定义变量时有无var声明的区别

    关于JavaScript中定义变量时有无var声明的区别 var a=5; //正确 a=5; //正确 在javascript中,以上两种方法都是定义变量的正确方法.微软的Script56.CHM中 ...

  8. 【LeetCode】144. Binary Tree Preorder Traversal (3 solutions)

    Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...

  9. iOS - CodeReview 代码评审

    1.CodeReview Code Review 中文应该译作 "代码审查" 或是 "代码评审",这是一个流程,当开发人员写好代码后,需要让别人来 review ...

  10. ASP.NET MVC ajax处理 AjaxResult

    1.统一ASPNET MVC 对ajax请求响应格式定义,方便前端统一处理ajax结果. 1)定义程序返回结果数据格式 /// <summary> /// 执行结果 /// </su ...