<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>アルゴリズム</title><link>http://blogs.wankuma.com/izmktr/category/1787.aspx</link><description>アルゴリズム</description><managingEditor>出水 洸太郎</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]クイックソートの広さ</title><link>http://blogs.wankuma.com/izmktr/archive/2008/11/13/161309.aspx</link><pubDate>Thu, 13 Nov 2008 23:04:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/11/13/161309.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/161309.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/11/13/161309.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/161309.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/161309.aspx</trackback:ping><description>&lt;P&gt;ネタ元&amp;gt;&lt;A href="http://bbs.wankuma.com/index.cgi?mode=al2&amp;amp;namber=27535"&gt;再帰をループに変換&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;クイックソートとは以下の順序でソートを行うものです。&lt;BR&gt;(1)ある要素を取り出し、その要素より小さいグループと大きいグループで分類する&lt;BR&gt;(2)それぞれのグループに対し、要素の数が1個になるまで(1)を繰り返す&lt;BR&gt;このクイックソートが必要とするメモリ量、すなわち空間計算量を考えてみましょう。&lt;/P&gt;
&lt;P&gt;要素を2つに分割した後、両方を同時に処理することはできません。&lt;BR&gt;ですから、一方はいったん置いて他方を処理します。&lt;BR&gt;その処理中にまた2つに分割されるため、いったん置いたうえにさらに置くことになります。&lt;BR&gt;図で表現するとこんな感じですね。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200811/qsort1.jpg"&gt; &lt;/P&gt;
&lt;P&gt;このようにうまく二等分できれば一時領域は10段もあれば十分です。&lt;BR&gt;この一時領域をスタックサイズと呼びます。&lt;/P&gt;
&lt;P&gt;別の場合のスタックサイズを考えてみます。&lt;BR&gt;こんな場合はどうでしょうか。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200811/qsort2.jpg"&gt; &lt;/P&gt;
&lt;P&gt;先ほどと違い、うまく分割することが出ていません。&lt;BR&gt;そして、このペースだとスタックサイズは500段必要です。&lt;/P&gt;
&lt;P&gt;一体スタックサイズは何段用意しておけばいいのでしょうか。&lt;BR&gt;出来るだけスタックサイズを小さくする方法を考えてみます。&lt;/P&gt;
&lt;P&gt;このスタックは処理中のものが終了するまで積まれ続けるわけです。&lt;BR&gt;いつ終了するんでしょうか。&lt;BR&gt;それは、処理中の要素数が2個以下になるまでです。&lt;/P&gt;
&lt;P&gt;それならば、早く処理中の要素数を減らせばよいわけです。&lt;BR&gt;2つに分割したとき、どちらをスタックに積み、どちらを処理中にするかは&lt;BR&gt;自由に決められるため、要素が多い方をスタックに積んでしまえばいいのです。&lt;/P&gt;
&lt;P&gt;それを図示しました。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200811/qsort3.jpg"&gt; &lt;/P&gt;
&lt;P&gt;いずれも4:1のグループに分かれていますが、左の方はもうすぐ処理が終わりそうです。&lt;BR&gt;このように、アンバランスに別れた方がスタックに積む量が減るため、&lt;BR&gt;最もスタックが必要なパターンは二等分されるパターンです。&lt;BR&gt;そして、二等分された場合、スタックサイズはlog2(N)必要です。&lt;/P&gt;
&lt;P&gt;よって、クイックソートの空間計算量は最悪の場合でもO(logN)です。&lt;/P&gt;
&lt;P&gt;なお、ピボットに使われた要素は処理済みにするのが好ましいため、&lt;BR&gt;1000個は499個＋1個＋500個のように3つに分けられますが&lt;BR&gt;今回は分かりやすくするため、それを無視しています。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/161309.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]マルチコア</title><link>http://blogs.wankuma.com/izmktr/archive/2008/10/30/160132.aspx</link><pubDate>Thu, 30 Oct 2008 06:33:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/10/30/160132.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/160132.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/10/30/160132.aspx#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/160132.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/160132.aspx</trackback:ping><description>&lt;P&gt;ネタ元＞&lt;A href="http://msdn.microsoft.com/ja-jp/magazine/cc850829.aspx"&gt;WindowsとC++：高性能アルゴリズムについて調べる&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;上記の記事を読むと、マルチコアで動作する時、&lt;BR&gt;同じコアで実行するメモリは近くに配置し、&lt;BR&gt;違うコアで実行するメモリは遠くに配置するべき、と書いています。&lt;/P&gt;
&lt;P&gt;さて、以前書いたシェアソートの並列動作なのですが、&lt;BR&gt;横ソートにおいては上記のマルチコア動作に向くメモリ配置になっています。&lt;/P&gt;
&lt;P&gt;しかし、縦ソートに至っては並列動作に向かないパターンです。&lt;BR&gt;良くないパターンとして紹介されている物と全く同じです。&lt;/P&gt;
&lt;P&gt;今回の場合は&amp;#8221;#pragma omp parallel for&amp;#8221;を使ったものなので&lt;BR&gt;自分でカリカリ内部動作を書いた場合とは違うのかもしれません。&lt;BR&gt;ただ、キャッシュの読み直しという単語がちらほら見えるので、&lt;BR&gt;ハードウェアの仕様のような感じで、ソフトウェア側でどうにかならない気がします。&lt;/P&gt;
&lt;P&gt;シェアソートの縦ソートが遅いとなるといよいよ出番もないですね&amp;#8230;。&lt;/P&gt;
&lt;P&gt;#ということで、教えて詳しい人！&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/160132.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]等号は続くよ どこまでも</title><link>http://blogs.wankuma.com/izmktr/archive/2008/10/23/159627.aspx</link><pubDate>Thu, 23 Oct 2008 01:02:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/10/23/159627.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/159627.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/10/23/159627.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/159627.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/159627.aspx</trackback:ping><description>&lt;P&gt;ネタ元：&lt;A href="http://blogs.wankuma.com/rti/archive/2008/10/22/159620.aspx"&gt;同じ値であること（その２）&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;aとbとcがすべて等しいという条件式を作ろうとして&lt;BR&gt;数学のようにa=b=cと書いてしまう人はよくいます。&lt;/P&gt;
&lt;P&gt;昔のBASICだと、if文の外でこのように書くとaに-1が代入されたりします。&lt;BR&gt;a=(b=c)と解釈され、(b=c)がtrueを意味する-1になるからです。&lt;/P&gt;
&lt;P&gt;そして、こんな書式も生まれました。&lt;/P&gt;
&lt;P&gt;I$=INKEY$&lt;BR&gt;x=x+(I$="4")-(I$="6")&lt;BR&gt;y=y+(I$="8")-(I$="2")&lt;/P&gt;
&lt;P&gt;I$は変数名で、INKEY$とは入力された文字を取得する関数です。&lt;BR&gt;つまり、4が入力されればxは-1され、6が入っていればxは+1されます。&lt;BR&gt;要はキャラクターやカーソルを動かす部分です。&lt;/P&gt;
&lt;P&gt;さらに、a=b=c=dはどうなるでしょうか。&lt;BR&gt;普通に解釈されるならa=(b=(c=d))ですね。&lt;/P&gt;
&lt;P&gt;しかし、(a=b)=(c=d)と捕えてみましょう。&lt;/P&gt;
&lt;P&gt;a=bがtrue 、c=dがtrue で全体がtrue&lt;BR&gt;a=bがtrue 、c=dがfalseで全体がfalse&lt;BR&gt;a=bがfalse、c=dがtrue で全体がfalse&lt;BR&gt;a=bがfalse、c=dがfalseで全体がtrue&lt;/P&gt;
&lt;P&gt;これは、排他的論理和(XOR)の否定を意味します。&lt;/P&gt;
&lt;P&gt;排他的論理和の演算子を用意していない言語でも、&lt;BR&gt;中央の等号をnot equalの記号にすれば排他的論理和を使うことができます。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/159627.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート6</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/28/157678.aspx</link><pubDate>Sun, 28 Sep 2008 20:03:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/28/157678.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157678.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/28/157678.aspx#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157678.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157678.aspx</trackback:ping><description>&lt;P&gt;前回で終わりのような気がしていたが別にそんなことはなかったぜ！&lt;/P&gt;
&lt;P&gt;今まで紹介したシェアソートは要素の数が平方数でした。&lt;BR&gt;サンプルなので奇麗に正方形に並べられる個数ばかり選んでたわけです。&lt;/P&gt;
&lt;P&gt;シェアソートは矩形(長方形)に並べられれば良いのですが、&lt;BR&gt;要素の数が素数だった場合はそれすら適いません。&lt;/P&gt;
&lt;P&gt;ということでそんな半端の状態のシェアソートです。&lt;/P&gt;
&lt;P&gt;39個の要素でシェアソートを行おうとすると、以下のようになります。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/hanpa1.jpg"&gt;&lt;/P&gt;
&lt;P&gt;実は、この形でも以下のように分割してシェアソートを行えば問題がありません。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/hanpa2.jpg"&gt;&lt;/P&gt;
&lt;P&gt;豆知識として、縦ソートをするときに40以上の位置を差したら終端としておくと、&lt;BR&gt;どこで数が変わったかというのを意識しないで済みます。&lt;/P&gt;
&lt;P&gt;ですが、折り返しで終わった場合はちょっと工夫が必要です。&lt;BR&gt;以下のような場合ですね。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/hanpa3.jpg"&gt;&lt;/P&gt;
&lt;P&gt;空白に最大値を入れてソートでも良いのですが、スマートではないです。&lt;BR&gt;そこで、1行6個ではなく7個で作りなおしてみます。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/hanpa4.jpg"&gt;&lt;/P&gt;
&lt;P&gt;うまく行きました。&lt;/P&gt;
&lt;P&gt;ちょうどいい一行の数の求め方ですが、今回はこうやっています。&lt;/P&gt;
&lt;P&gt;　44 &amp;#247; 6 = 7 余り 2&lt;/P&gt;
&lt;P&gt;1行6個で並べれば7行と2個と読めますが、&lt;BR&gt;逆に1行7個で並べれば6行と2個という読み方をします。&lt;BR&gt;適当な偶数で割ってやってその商を1行の個数とすれば&lt;BR&gt;必ず都合のいい配置になってくれるわけです。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157678.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート5</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/26/157509.aspx</link><pubDate>Fri, 26 Sep 2008 02:59:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/26/157509.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157509.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/26/157509.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157509.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157509.aspx</trackback:ping><description>&lt;P&gt;多次元シェアソートの行きつく先を見てみましょう。&lt;/P&gt;
&lt;P&gt;要素が増えたとき、1辺の長さを出来るだけ短くしたまま&lt;BR&gt;次元数だけをどんどん増やしてソートを行う事を考えてみます。&lt;/P&gt;
&lt;P&gt;最も短い1辺の長さは2です。&lt;BR&gt;256個の要素があったら、1辺が2の八次元立方体を作ってソートします。&lt;/P&gt;
&lt;P&gt;また、最後に逆にするのは面倒なので、&lt;BR&gt;ソートする要素の選び方を工夫して&lt;BR&gt;配列は正しい順に並べたままソートをする方法を考えます。&lt;/P&gt;
&lt;P&gt;まずは、要素が8個、つまり一辺2の三次元立方体で考えます。&lt;BR&gt;以下の図ができます。&lt;/P&gt;
&lt;P&gt;&lt;img src=http://izmktr.wankuma.com/200809/s2_1.jpg&gt;&lt;/P&gt;
&lt;P&gt;そして、横ソート、縦ソート、段ソートのペアを抽出してみます。&lt;/P&gt;
&lt;P&gt;横ソート　[1, 2] [3, 4] [5, 6] [7, 8]&lt;BR&gt;縦ソート　[1, 4] [2, 3] [5, 8] [6, 7]&lt;BR&gt;段ソート　[1, 8] [2, 7] [3, 6] [4, 5]&lt;/P&gt;
&lt;P&gt;さらにこれを図示します。&lt;/P&gt;
&lt;P&gt;&lt;img src=http://izmktr.wankuma.com/200809/s2_2.jpg&gt;&lt;/P&gt;
&lt;P&gt;意外に単純な図が出来上がりました。&lt;BR&gt;これなら、棟ソート(四次元方向ソート)やその上も簡単に作れるでしょう。&lt;/P&gt;
&lt;P&gt;さて、要素が4つの場合は「横ソート→縦ソート→横ソート」の方法で完了しました。&lt;BR&gt;ではこの要素が8個の場合は何所に段ソートを入れればいいでしょうか。&lt;/P&gt;
&lt;P&gt;実は、段ソートを行っていい条件として&lt;BR&gt;縦ソート、横ソート共に完了する必要があります。&lt;BR&gt;それ以前に段ソートを実行しても、ある程度は揃うけど完璧ではないのです。&lt;/P&gt;
&lt;P&gt;つまり、三次元シェアソートは以下のようにソートをします。&lt;BR&gt;「横ソート→縦ソート→横ソート→段ソート→&lt;BR&gt;　横ソート→縦ソート→横ソート」&lt;BR&gt;まるで二進数のビットが立っていく様子に似ています。&lt;/P&gt;
&lt;P&gt;では、x個の要素(x=2^n)があったときの比較回数を求めてみましょう。&lt;BR&gt;まず、ソート1回ではx/2回の比較が行われます。&lt;BR&gt;そして、ソート回数は(x-1)回行われます。&lt;BR&gt;よって、完了まで必要なソート回数は(x/2)(x-1)です！&lt;/P&gt;
&lt;P&gt;あれ&amp;#8230;ランダウの記号を用いるとこれは&amp;#8230;O(n^2)なのでは？？&lt;/P&gt;
&lt;P&gt;ということで、これ以上進んでも深みにはまるだけっぽいので&lt;BR&gt;シェアソートはこれで終わりにしたいと思います。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157509.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート4</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/25/157442.aspx</link><pubDate>Thu, 25 Sep 2008 01:06:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/25/157442.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157442.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/25/157442.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157442.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157442.aspx</trackback:ping><description>&lt;P&gt;まだまだ続くシェアソート&lt;BR&gt;今回は多次元展開です。&lt;/P&gt;
&lt;P&gt;シェアソートは二次元平面上に展開することで高速化を図りましたが、&lt;BR&gt;三次元空間上に展開したらどうなるでしょうか。&lt;BR&gt;まずは、図を見てみましょう。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/dim3.jpg"&gt;&lt;BR&gt;これが三次元展開の配置です。&lt;BR&gt;三次元方向には段という名前で呼びます。&lt;BR&gt;2段目は1段目の逆、すなわち開始点と終了点が逆になるようにソートを行っていきます。&lt;BR&gt;3段目は1段目と同じようにソートします。&lt;BR&gt;ソート条件は以下のように変化します。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;段ソートは、常に昇順&lt;/LI&gt;
&lt;LI&gt;縦ソートは、奇数段なら昇順、偶数段なら降順&lt;/LI&gt;
&lt;LI&gt;横ソートは、段数＋行数が奇数なら昇順、偶数なら降順&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;この要領で、四次元展開まで行ってみましょう。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/dim4.jpg"&gt;&lt;BR&gt;四次元方向には棟という名前を付けます。&lt;BR&gt;それぞれの立方体を団地とみなし、1号棟、2号棟と増えていく様子を想像してください。&lt;/P&gt;
&lt;P&gt;1号棟は1で始まり、27で終わりました。&lt;BR&gt;2号棟の始まる28は、1号棟の27のあった位置になります。&lt;BR&gt;そして、26の位置が29になり、25の位置が29になり&amp;#8230;1の位置が54となります。&lt;BR&gt;つまり、2号棟は3段目に小さい数字が来て、1段目が大きな数字が来ます。&lt;BR&gt;3号棟は1号棟と同じ形で並んでいます。&lt;/P&gt;
&lt;P&gt;では、ソート条件を四次元で考えましょう。&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;棟ソートは、常に昇順&lt;/LI&gt;
&lt;LI&gt;段ソートは、奇数棟なら昇順、偶数棟なら降順&lt;/LI&gt;
&lt;LI&gt;縦ソートは、棟数＋段段が奇数なら昇順、偶数なら降順&lt;/LI&gt;
&lt;LI&gt;横ソートは、棟数＋段数＋行数が奇数なら昇順、偶数なら降順&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;なお、シェアソートが終わった後、逆になっているものを元に戻すことを考えたとき、&lt;BR&gt;棟の逆転→段の逆転→行の逆転と3ステップ踏まないと完全に戻りません。&lt;/P&gt;
&lt;P&gt;多次元におけるシェアソートを考えてみましたが、さほど効率が良いように思えません。&lt;BR&gt;次回、多次元シェアソートをもう少し考えて、長々と続いたシェアソートの補足を終わりたいと思います。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157442.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート3</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/23/157322.aspx</link><pubDate>Tue, 23 Sep 2008 06:32:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/23/157322.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157322.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/23/157322.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157322.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157322.aspx</trackback:ping><description>&lt;PRE class=VB name="code"&gt;Sub 縦方向ソート()
    Dim i As Integer
    Dim waku As Range
    
    For i = 0 To columnmax - 1
        Set waku = Range(Cells(1, i + 1), Cells(rowmax, i + 1))
        waku.Sort key1:=Cells(1, i + 1), order1:=xlAscending, Orientation:=xlSortColumns
    Next
End Sub

Sub 横方向ソート()
    Dim i As Integer
    Dim waku As Range
    
    For i = 0 To rowmax - 1
        Set waku = Range(Cells(i + 1, 1), Cells(i + 1, columnmax))
        If i Mod 2 = 0 Then
            waku.Sort key1:=Cells(i + 1, 1), order1:=xlAscending, Orientation:=xlSortRows
        Else
            waku.Sort key1:=Cells(i + 1, 1), order1:=xlDescending, Orientation:=xlSortRows
        End If
    Next
End Sub
&lt;/PRE&gt;
&lt;P&gt;上はエクセルのマクロの抜粋です。&lt;BR&gt;ごめんなさい、思いっきり手を抜きました。&lt;/P&gt;
&lt;P&gt;ソートを作るんだから、既存のソート関数を使ってはいけないのですが、&lt;BR&gt;思いっきりSortという文字が見えます。&lt;/P&gt;
&lt;P&gt;今回は、縦ソート、横ソートに何を使うか考えてみます。&lt;/P&gt;
&lt;P&gt;普通に考えればシェアソートを再帰する方法です。&lt;BR&gt;ですが、シェアソートは順列（すでにソート済みの状態）であっても&lt;BR&gt;交換が発生してしまうため、順列の検出が出来ません。&lt;/P&gt;
&lt;P&gt;なお、縦ソート、横ソート共に交換が発生しなかったら終了という条件ですが、&lt;BR&gt;実際には2回目以降なら縦ソートか横ソートのどちらかで順列を検出すればOKです。&lt;BR&gt;なぜなら、縦ソート後は縦ソートをしても交換が発生しない状態だからです。&lt;/P&gt;
&lt;P&gt;順列の検出といえばバブルソートです。&lt;BR&gt;これを縦ソートに使ってやれば順列の検出が出来るし、&lt;BR&gt;縦ソートはそれほど要素が変わらないため、&lt;BR&gt;バブルソートでも十分速度が出ると考えられます。&lt;/P&gt;
&lt;P&gt;ただし、横ソートにバブルソートを使った場合、&lt;BR&gt;最大要素や最小要素が先頭や末尾に来ることが多いため&lt;BR&gt;バブルソートの最悪パターンに陥りやすいため、不向きと言えるでしょう。&lt;BR&gt;こちらはシェアソートを再帰させるべきです。&lt;/P&gt;
&lt;P&gt;なお、最初の縦ソートに限っては、要素がバラバラである上&lt;BR&gt;順列検出も必要ないため、こちらはシェアソートで十分に思えます。&lt;/P&gt;
&lt;P&gt;あとは、要素が少ない場合はバブルソートでいいでしょう。&lt;BR&gt;どこを閾値にするか難しいですが、一辺が3以下になる16未満としておきます。&lt;/P&gt;
&lt;P&gt;よって、改良シェアソートのアルゴリズムは以下のようになります。&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;要素が16未満ならバブルソートを行い、終了する。 
&lt;LI&gt;シェアソートを使い、縦ソートを行う。 
&lt;LI&gt;繰り返し回数を求める。（ n = log(√n) ） 
&lt;LI&gt;シェアソートを使い横ソートを行う。&lt;BR&gt;このとき、奇数行は昇順、偶数行は降順になるようにする。 
&lt;LI&gt;バブルソートを使い縦ソートを行う。 
&lt;LI&gt;縦ソートで、すべての列で交換が発生しない場合、偶数行を反転して終了する。 
&lt;LI&gt;4.～7.を回数分繰り返す。 
&lt;LI&gt;シェアソートを使い横ソートを行う。&lt;BR&gt;すべての行で昇順になるようにする。&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;なお、ここでバブルソートを使っていますが、&lt;BR&gt;クイックソート等の高速ソートだとどうでしょうか。&lt;/P&gt;
&lt;P&gt;結論から言うと、シェアソートとクイックソートを組み合わせるより&lt;BR&gt;最初からクイックソートを使った方が速いです。&lt;/P&gt;
&lt;P&gt;せっかく改良したのにまさに無駄骨です。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157322.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート2</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157226.aspx</link><pubDate>Sun, 21 Sep 2008 15:35:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157226.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157226.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157226.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157226.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157226.aspx</trackback:ping><description>&lt;P&gt;シェアソートでは、2n+1(nは前回出てきた複雑な式)の回数ソートしたときを終了とし、&lt;BR&gt;途中でソートが終了してもそれを検知しません。&lt;BR&gt;一見無駄じゃないか、と思うので調べてみました。&lt;/P&gt;
&lt;P&gt;10000個(100&amp;#215;100)のすべてユニークなランダムにした要素をソートします。&lt;BR&gt;このとき、理論上では15回ソートが必要です。&lt;BR&gt;実際にやってみた結果&amp;#8230;なんと、20回中19回が15回目のソートで完了し、&lt;BR&gt;残りの1回は13回目のソートで完了、という結果になりました。&lt;/P&gt;
&lt;P&gt;よって、途中でソート終了を検知するのはあまり効果がないと結論付けられそうです。&lt;/P&gt;
&lt;P&gt;マクロを動かした人なら気づくかもしれませんが、実感とずれてないでしょうか。&lt;BR&gt;シェアソートマクロの場合は11&amp;#215;11なので9回ソートが必要なのですが、&lt;BR&gt;そんなにソートしなくても終了していたという気がしませんか。&lt;BR&gt;現にライトニングトークでは6回のソートで終了しています。&lt;/P&gt;
&lt;P&gt;理由は、最初に行ったソートです。&lt;BR&gt;古典的シェアソートは横ソートからスタートしますが、縦ソートからスタートしている人が多いはずです。&lt;/P&gt;
&lt;P&gt;最初に縦ソートをすると、その縦ソートが無駄になる場合もあるので、&lt;BR&gt;完了までに必要な最大ソート回数が1回増えます。&lt;/P&gt;
&lt;P&gt;冒頭で出た10000個のソートを、最初に縦ソートを行うように変更して試行します。&lt;BR&gt;20回中、10回が8回目のソートで終了し、10回が10回目のソートで終了しました。&lt;BR&gt;最初に横ソートを行うより、ずいぶんと速いです。&lt;/P&gt;
&lt;P&gt;なぜこんな差が出るのか、シェアソートマクロで見てみます。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/b1.jpg"&gt;&lt;BR&gt;このデータに対して、まず縦ソートを行います。&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/b2.jpg"&gt;&lt;BR&gt;このようなソート結果になりました。&lt;BR&gt;次は横ソートを見てみます。&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/b3.jpg"&gt;&lt;BR&gt;横ソートを行いました。&lt;BR&gt;この段階ではまだ違いが分かりにくいので、さらに縦ソートを行ってみます。&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/b4.jpg"&gt;&lt;BR&gt;最初に縦ソートを行った場合と比較してみましょう。&lt;/P&gt;
&lt;P&gt;最初に縦ソートを行った場合はずいぶんと平らなのに対し、&lt;BR&gt;横ソートを行った場合は四隅に寄るような形になっています。&lt;BR&gt;青色の高さに注目すると、縦ソート版は3なのに対し、横ソート版は5です。&lt;/P&gt;
&lt;P&gt;前回のエントリーで、高さを低くしていく必要がある、と書きました。&lt;BR&gt;ですから、最初から高さが低い方がソートは速く進むのです。&lt;BR&gt;ランダムに並んでいる場合は縦ソートできれいに低くなるのですが、&lt;BR&gt;横ソートで大きい要素や小さい要素を端に集めてしまうと、高さが高くなってしまいます。&lt;/P&gt;
&lt;P&gt;最大ソート回数が1回多くなっても、縦ソートを先に行うべきだと思います。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157226.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]はみだしシェアソート1</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157207.aspx</link><pubDate>Sun, 21 Sep 2008 02:11:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157207.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157207.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/21/157207.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157207.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157207.aspx</trackback:ping><description>&lt;P&gt;勉強会お疲れ様でした。&lt;/P&gt;
&lt;P&gt;ながせさんが基礎で、えぴさんが応用で、私がひねくれ者と、&lt;BR&gt;三者三様でかぶらないところが素敵でした。&lt;/P&gt;
&lt;P&gt;さて、シェアソートの基本的な所は、&lt;A href="http://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%82%A2%E3%82%BD%E3%83%BC%E3%83%88"&gt;Wikipediaによる解説&lt;/A&gt;や&lt;BR&gt;&lt;A href="http://blogs.wankuma.com/izmktr/archive/2008/09/20/157178.aspx"&gt;前回のエントリー&lt;/A&gt;のマクロを動かしてもらうとして、書ききれなかった所を書いていきます。&lt;/P&gt;
&lt;P&gt;数字が複雑に動くので、何回やったらソートが終わるのか不安になりますが、&lt;BR&gt;これは明確に回数が求められます。&lt;/P&gt;
&lt;P&gt;最悪パターンを見ながらその仕組みを説明します。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/t1.jpg"&gt;&amp;nbsp;&lt;BR&gt;このように、1行に収まるべきデータが縦になっている状態が最悪パターンで、&lt;BR&gt;最もソート完了まで時間がかかる状態です。&lt;BR&gt;なお、青色の要素は最後に先頭行に、橙色の要素は最後に末尾行に来る要素です。&lt;BR&gt;緑はちょうど真ん中の行に来る要素です。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/t2.jpg"&gt;&amp;nbsp;&lt;BR&gt;まずは、横ソートを行います。&lt;BR&gt;最上段の要素と最下段の要素が左右に二分されました。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/t3.jpg"&gt;&lt;BR&gt;上記のデータに縦ソートを行いました。&lt;BR&gt;青、橙の高さが半分になっています。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;IMG src="http://izmktr.wankuma.com/200809/t4.jpg"&gt; &lt;BR&gt;さらに横ソート→縦ソートを行いました。&lt;BR&gt;青、橙の要素は6→3と半分になっています。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/t5.jpg"&gt; &lt;BR&gt;さらに横ソート→縦ソートを行いました。&lt;BR&gt;段々と一行にまとまっていこうとしています。&lt;BR&gt;このように、横ソート→縦ソートのセットで高さが半分になっていくのです。&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://izmktr.wankuma.com/200809/t6.jpg"&gt;&lt;BR&gt;さらに横ソート→縦ソートを行うと、すべての要素で行が合うようになりました。&lt;BR&gt;このあと、横ソートを行って仕上げを行います。&lt;/P&gt;
&lt;P&gt;このように、高さが1になるまでソートを繰り返せばよく、&lt;BR&gt;一度横ソート→縦ソートを行うと高さが半分になるため、&lt;BR&gt;一辺の長さを何回2で割れば1以下となるか、という問題に帰着します。&lt;/P&gt;
&lt;P&gt;今回の場合は、11&amp;#215;11なので、一辺の長さは11です。&lt;BR&gt;11は8&amp;lt;11&amp;lt;16のため、4回割ってやれば1になります。&lt;BR&gt;横ソート→縦ソートのセットが4回と、最後の仕上げの横ソートをくわえ、&lt;BR&gt;121個の要素の場合は、9回ソートを行えば完了することになります。&lt;/P&gt;
&lt;P&gt;これを数学的に書くと、&lt;IMG src="http://izmktr.wankuma.com/200809/log2n.gif"&gt;という式ができあがります。&lt;BR&gt;何回2で割れば1以下になるか、というのを表現する部分がややこしくなってますね。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157207.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>出水 洸太郎</dc:creator><title>[アルゴリズム]シェアソートLT</title><link>http://blogs.wankuma.com/izmktr/archive/2008/09/20/157178.aspx</link><pubDate>Sat, 20 Sep 2008 12:14:00 GMT</pubDate><guid>http://blogs.wankuma.com/izmktr/archive/2008/09/20/157178.aspx</guid><wfw:comment>http://blogs.wankuma.com/izmktr/comments/157178.aspx</wfw:comment><comments>http://blogs.wankuma.com/izmktr/archive/2008/09/20/157178.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/izmktr/comments/commentRss/157178.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/izmktr/services/trackbacks/157178.aspx</trackback:ping><description>&lt;P&gt;ソートライトニングトークで使った&lt;BR&gt;&lt;A href="http://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%82%A2%E3%82%BD%E3%83%BC%E3%83%88"&gt;シェアソート&lt;/A&gt;を行うエクセルマクロを公開します。&lt;/P&gt;
&lt;P&gt;いろいろ機能を盛り込んでいるのでぜひ試してください。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://izmktr.wankuma.com/200809/sort.zip"&gt;ダウンロード&lt;/A&gt;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/izmktr/aggbug/157178.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>