Как я реализую quicksort использование пакетного файла?

11
задан Cody Hatch 25 September 2008 в 12:55
поделиться

1 ответ

Оказывается, это не настолько твердо, как Вы могли бы думать. Синтаксис ужасен как черт, но пакетный синтаксис на самом деле способен к некоторым удивительным вещам, включая рекурсию, локальные переменные и некоторый удивительно сложный парсинг строк. Не понимайте меня превратно, это - ужасный язык, но к моему удивлению, этому не полностью наносят вред. Я не думаю, что узнал что-либо о 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. Ключевые биты - то, что мы храним числа в строке - массив бедного человека. Второе для цикла довольно неясно, он в основном разделяет массив на голову (первый элемент) и хвост (все другие элементы). Haskell делает это с нотацией x:xs, но пакетные файлы делают это с для цикла, названного с переключателем/f. Почему? Почему нет?

SETLOCAL и вызовы ENDLOCAL позволяют нам сделать локальные переменные - вид. SETLOCAL дает нам полную копию исходных переменных, но все изменения полностью вытерты, когда мы называем ENDLOCAL, что означает, что Вы не можете даже общаться с функцией вызова, использующей globals. Это объясняет ужасный "ENDLOCAL и возврат набора =, % отсортировал %" синтаксис, который на самом деле работает несмотря на то, на что указала бы логика. Когда строка выполняется, отсортированная переменная не была вытерта, потому что строка еще не была выполнена - затем впоследствии, возвращаемая переменная не вытерта, потому что строка была уже выполнена. Логичный!

Кроме того, забавно, Вы в основном не можете использовать переменные в для цикла, потому что они не могут измениться - который удаляет большую часть точки наличия для цикла. Обходное решение должно установить ENABLEDELAYEDEXPANSION, который работает, но делает синтаксис еще более ужасным, чем нормальный. Заметьте, что у нас теперь есть соединение переменных, на которые ссылается только их имя, путем добавления префикса их единственный %, путем добавления префикса их два %, путем обертывания их в %, или путем обертывания их в!. И эти различные способы сослаться на переменные являются почти полностью НЕ взаимозаменяемыми!

Кроме этого, должно быть относительно легко понять!

23
ответ дан 3 December 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: