最後に今まで出てこなかったソートをやりたいと思います。
まず、選択ソートはforが使えるので書きやすく、意外と速いです。
それから、クイックソートです。クイックソートは再帰で書きますが、setlocalが使えないので変数を退避してくれません。退避しなければならないのはピボットの位置です。自力でスタックを作ろうかと思ったのですが、よく考えると呼び出された再帰関数のほうでその位置を返せばいいことに気がつきました。
以下は、選択ソートとクイックソートの処理速度のベンチマークです。要素数が500以上だとクイックソートが速いという結果になりました。組み合わせると速いんでしょうけどね。
size | 選択ソート | クイックソート |
---|---|---|
10 | 0.05s | 0.17s |
20 | 0.12s | 0.36s |
50 | 0.40s | 1.30s |
100 | 1.26s | 3.18s |
200 | 5.10s | 8.88s |
500 | 46.46s | 28.35s |
1000 | 311.14s | 81.41s |
今までのコードでバッチファイルの可能性を示せたのではないかと思います。しかし、なかなかデバッグが大変でした。
:sort set /a size = "%1.size" set /a size_1 = %size% - 1 set /a size_2 = %size% - 2 for /L %%i in (0, 1, %size_2%) do ( set /a min = "%1_%%i" set /a i_1 = %%i + 1 set /a k = %%i for /L %%j in (!i_1!, 1, %size_1%) do ( set /a e = "%1_%%j" if !e! LSS !min! ( set /a min = !e! set /a k = %%j ) ) set /a tmp = "%1_%%i" call set /a %1_%%i = %%%1_!k!%% set /a %1_!k! = !tmp! ) exit /b 0
@echo off setlocal enabledelayedexpansion set /a N = %1 set /a N_1 = %N% - 1 set /a t = 123456 for /L %%k in (0, 1, %N_1%) do ( set /a r = !t! %% 2 set /a t /= 2 if !r! == 1 set /a "t ^= 926252" set /a b_%%k = !t! ) set /a b.size = %N% call :start_time call :qsort b call :check_time call :check_sort b echo %ERRORLEVEL% exit /b 0 :qsort set /a size = "%1.size" call :qsort_core %1 0 %size% exit /b 0 :qsort_core set /a size = %3 - %2 if %size% LEQ 1 exit /b %3 rem // frontより小さい大きいで振り分ける set /a front = "%1_%2" set /a begin = %2 + 1 set /a end = %3 - 1 set /a i = %2 set /a j = %end% for /L %%k in (%begin%, 1, %end%) do ( set /a e = "%1_%%k" if !e! LSS %front% ( call set /a tmp_!i! = !e! set /a i += 1 ) else ( call set /a tmp_!j! = !e! set /a j -= 1 ) ) set /a tmp_%i% = %front% for /L %%k in (%2, 1, %3) do ( set /a %1_%%k = "tmp_%%k" ) call :qsort_core %1 %2 %i% set /a end = %ERRORLEVEL% + 1 call :qsort_core %1 %end% %3 exit /b %3 :check_sort setlocal set /a max_index = "%1.size" - 1 for /L %%k in (1, 1, %max_index%) do ( set /a l = %%k - 1 call set /a prev = %%%1_!l!%% call set /a next = %%%1_%%k%% if !prev! GTR !next! exit /b 0 ) exit /b 1 :print_vector setlocal set /a size = "%1.size" if %size% == 0 echo %2 & exit /b 0 set /a e = "%1_0" set s=%e% set /a k = 1 :loop_print_vector if %k% == %size% echo %s% & exit /b 0 set /a e = "%1_%k%" set s=%s% %e% set /a k += 1 goto :loop_print_vector :start_time call :get_time set /a __t0 = %ERRORLEVEL% exit /b 0 :check_time setlocal call :get_time set /a t = %ERRORLEVEL% - %__t0% if %t% LSS 10 ( echo 0.0%t%s ) else ( if %t% LSS 100 ( echo 0.%t%s ) else ( echo %t:~0,-2%.%t:~-2%s ) ) exit /b 0 :get_time setlocal set t=%TIME% set /a h = %t:~0,2% set /a m = 1%t:~3,2% %% 100 set /a s = 1%t:~6,2% %% 100 set /a ss = 1%t:~-2% %% 100 set /a ret = ((%h% * 60 + %m%) * 60 + %s%) * 100 + %ss% exit /b %ret%