如何使用批处理文件实施quicksort?
通常情况下,总是为工作选择正确的语言是很好的选择,但是有时尝试以一种非常不合适的语言来做某事可能会很有帮助。
- 它可以更好地理解问题。也许我们不必以我们认为的方式来解决它。
- 它可以更好地理解语言。也许它支持的功能比我们想象的要多。
并将这个想法推向不合逻辑的结论...我们将如何在批处理文件中实现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设置为有效,但使语法比正常情况更丑陋。请注意,现在我们混合了一些变量,这些变量仅通过名称来引用,可以在变量前加上一个%,在变量前加上两个%,在变量中包装成%,或者在变量中包含!这些引用变量的不同方法几乎是完全不能互换的!
除此之外,它应该相对容易理解!