【问题标题】:How do I implement quicksort using a batch file?如何使用批处理文件实现快速排序?
【发布时间】:2010-09-13 02:04:53
【问题描述】:

虽然通常总是为工作选择正确的语言是件好事,但有时尝试用一种非常不合适的语言做某事可能会很有启发性。

  1. 它可以帮助您更好地理解问题。也许你没有按照你认为的方式解决它。
  2. 它可以帮助您更好地理解语言。也许它支持的功能比您想象的要多。

将这个想法推向不合逻辑的结论......你将如何在批处理文件中实现快速排序?有没有可能?

【问题讨论】:

    标签: sorting batch-file


    【解决方案1】:

    这是我不久前写的一个更清晰的版本:

    @echo off
    
    echo Sorting:  %*
    
    set sorted=
    
    :sort
    :: If we've only got one left, we're done.
    if "%2"=="" (
      set sorted=%sorted% %1
      :: We have to do this so that sorted gets actually set before we print it.
      goto :finalset
    )
    :: Check if it's in order.
    if %1 LEQ %2 (
      :: Add the first value to sorted.
      set sorted=%sorted% %1
      shift /1
      goto :sort
    )
    :: Out of order.
    :: Reverse them and recursively resort.
    set redo=%sorted% %2 %1
    set sorted=
    shift /1
    shift /1
    :loop
    if "%1"=="" goto :endloop
    set redo=%redo% %1
    shift /1
    goto :loop
    :endloop
    call :sort %redo%
    :: When we get here, we'll have already echod our result.
    goto :eof
    
    :finalset
    echo Final Sort:  %sorted%
    goto :eof
    

    例子:

    C:\Path> sort 19 zebra blah 1 interesting 21 bleh 14 think 2 ninety figure it out
    

    产生:

    Sorting:  19 zebra blah 1 interesting 21 bleh 14 think 2 ninety figure it out
    Final Sort:   1 2 14 19 21 blah bleh figure interesting it ninety out think zebra
    

    【讨论】:

    • 太棒了。很高兴看到我不是唯一一个无聊的人...... :)
    【解决方案2】:

    事实证明,这并不像您想象的那么难。语法丑得要命,但批处理语法实际上能够做一些令人惊讶的事情,包括递归、局部变量和一些令人惊讶的复杂字符串解析。不要误会我的意思,这是一种糟糕的语言,但令我惊讶的是,它并没有完全瘫痪。我认为我没有学到任何关于快速排序的知识,但我学到了很多关于批处理文件的知识!

    无论如何,这里是批处理文件中的快速排序 - 我希望您在阅读它时像我在编写它时一样尝试理解奇怪的语法。 :-)

    @echo off
    SETLOCAL ENABLEDELAYEDEXPANSION
    
    call :qSort %*
    for %%i in (%return%) do set results=!results! %%i
    echo Sorted result: %results%
    ENDLOCAL
    goto :eof
    
    :qSort
    SETLOCAL
        set list=%*
        set size=0
        set less=
        set greater=
        for %%i in (%*) do set /a size=size+1
        if %size% LEQ 1 ENDLOCAL & set return=%list% & goto :eof
        for /f "tokens=2* delims== " %%i in ('set list') do set p=%%i & set body=%%j
        for %%x in (%body%) do (if %%x LEQ %p% (set less=%%x !less!) else (set greater=%%x !greater!))
        call :qSort %less%
        set sorted=%return%
        call :qSort %greater%
        set sorted=%sorted% %p% %return%
    ENDLOCAL & set return=%sorted%
    goto :eof
    

    通过给它一组数字来调用它,以便在命令行上排序,用空格分隔。示例:

    C:\dev\sorting>qsort.bat 1 3 5 1 12 3 47 3
    Sorted result:  1 1 3 3 3 5 12 47
    

    代码有点难理解。它基本上是标准的快速排序。关键是我们将数字存储在一个字符串中——穷人的数组。第二个 for 循环非常模糊,它基本上将数组拆分为头部(第一个元素)和尾部(所有其他元素)。 Haskell 使用符号 x:xs 执行此操作,但批处理文件使用 /f 开关调用的 for 循环执行此操作。为什么?为什么不呢?

    SETLOCAL 和 ENDLOCAL 调用让我们可以处理局部变量 - 有点像。 SETLOCAL 为我们提供了原始变量的完整副本,但是当我们调用 ENDLOCAL 时,所有更改都被完全擦除,这意味着您甚至无法使用全局变量与调用函数进行通信。这解释了丑陋的“ENDLOCAL & set return=%sorted%”语法,尽管逻辑表明它实际上是有效的。执行该行时,由于该行尚未执行,因此尚未擦除已排序的变量-然后由于该行已执行该行,因此未擦除返回变量。合乎逻辑!

    另外,有趣的是,你基本上不能在 for 循环中使用变量,因为它们不能改变 - 这消除了 for 循环的大部分意义。解决方法是设置 ENABLEDELAYEDEXPANSION 有效,但会使语法比正常情况更难看。请注意,我们现在有一个混合变量,仅通过它们的名称引用,通过在它们前面加上一个 %,通过在它们前面加上两个 %,通过将它们包装在 % 中,或者通过将它们包装在 ! 中。而且这些引用变量的不同方式几乎是完全不可互换的!

    除此之外,应该比较容易理解!

    【讨论】:

    • 多么棒的答案啊。好样的科迪!
    • 丑得可爱,就像哈巴狗一样。
    猜你喜欢
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多