如何使用批处理文件实施quicksort?

时间:2020-03-06 14:43:08  来源:igfitidea点击:

通常情况下,总是为工作选择正确的语言是很好的选择,但是有时尝试以一种非常不合适的语言来做某事可能会很有帮助。

  • 它可以更好地理解问题。也许我们不必以我们认为的方式来解决它。
  • 它可以更好地理解语言。也许它支持的功能比我们想象的要多。

并将这个想法推向不合逻辑的结论...我们将如何在批处理文件中实现quicksort?可能吗?

解决方案

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

无论如何,这是一个批处理文件中的quicksort,我希望我们在阅读它时像在编写它时一样,试图理解奇怪的语法也很有趣。 :-)

@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

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

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

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

除此之外,它应该相对容易理解!