<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>@blog.justoneplanet.info &#187; アルゴリズム</title>
	<atom:link href="http://blog.justoneplanet.info/category/computer/algorithm/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.justoneplanet.info</link>
	<description>日々勉強</description>
	<lastBuildDate>Wed, 08 Feb 2012 02:57:17 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Goolge Developer Day 2011のWeb Gameを解いてみる</title>
		<link>http://blog.justoneplanet.info/2011/09/13/goolge-developer-day-2011%e3%81%aeweb-game%e3%82%92%e8%a7%a3%e3%81%84%e3%81%a6%e3%81%bf%e3%82%8b/</link>
		<comments>http://blog.justoneplanet.info/2011/09/13/goolge-developer-day-2011%e3%81%aeweb-game%e3%82%92%e8%a7%a3%e3%81%84%e3%81%a6%e3%81%bf%e3%82%8b/#comments</comments>
		<pubDate>Mon, 12 Sep 2011 22:00:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=4358</guid>
		<description><![CDATA[Extensionとか入れたりするの面倒なので以下のJavaScriptをコンソールに打ち込む。 var ary = []; for(var i = 0; i &#60; 1024; i++){ if($('card' + [...]]]></description>
			<content:encoded><![CDATA[<p>Extensionとか入れたりするの面倒なので以下のJavaScriptをコンソールに打ち込む。</p>
<pre class="brush: jscript;">
var ary = [];
for(var i = 0; i &lt; 1024; i++){
    if($('card' + i)){
        $('#card' + i).click();
        ary.push($('#card' + i).css('backgroundColor'));
    }
}
ary.forEach(function(elm, i1, ary){
    for(var i2 = i1 + 1; i2 &lt; ary.length; i2++){
        if(ary[i1] == ary[i2]){
            $('#card' + i1).click();
            $('#card' + i2).click();
        }
    }
});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/09/13/goolge-developer-day-2011%e3%81%aeweb-game%e3%82%92%e8%a7%a3%e3%81%84%e3%81%a6%e3%81%bf%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptでプリム法</title>
		<link>http://blog.justoneplanet.info/2011/06/13/javascript%e3%81%a7%e3%83%97%e3%83%aa%e3%83%a0%e6%b3%95/</link>
		<comments>http://blog.justoneplanet.info/2011/06/13/javascript%e3%81%a7%e3%83%97%e3%83%aa%e3%83%a0%e6%b3%95/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 16:09:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=4139</guid>
		<description><![CDATA[重み付き無向グラフの最小全域木を求めるアルゴリズム。任意の辺から始めて全頂点を覆うまで連続的に木の大きさを拡大し、全ての辺の重みの総和が最小となる経路を求める。 ■実装 以下のように実装した。 /** * Vertex  [...]]]></description>
			<content:encoded><![CDATA[<p>重み付き無向グラフの最小全域木を求めるアルゴリズム。任意の辺から始めて全頂点を覆うまで連続的に木の大きさを拡大し、全ての辺の重みの総和が最小となる経路を求める。</p>
<h3>■実装</h3>
<p>以下のように実装した。</p>
<pre class="brush: jscript;">
/**
 * Vertex
 * @param int value
 */
var Vertex = function(value){
    var self = this;
    self.value    = value;
    self.neighbor = [];
    self.appendNeighbor = function(){
        for(var i = 0; i &lt; arguments.length; i++){
            self.neighbor.push(arguments[i]);
        }
    }
}

// set up a graph
var v0 = new Vertex(0);
var v1 = new Vertex(1);
var v2 = new Vertex(2);
var v3 = new Vertex(3);
var v4 = new Vertex(4);
v0.appendNeighbor(
    {&quot;vertex&quot; : v1, &quot;weight&quot; : 2},
    {&quot;vertex&quot; : v3, &quot;weight&quot; : 8},
    {&quot;vertex&quot; : v4, &quot;weight&quot; : 4}
);
v1.appendNeighbor(
    {&quot;vertex&quot; : v0, &quot;weight&quot; : 2},
    {&quot;vertex&quot; : v2, &quot;weight&quot; : 3}
);
v2.appendNeighbor(
    {&quot;vertex&quot; : v1, &quot;weight&quot; : 3},
    {&quot;vertex&quot; : v4, &quot;weight&quot; : 1},
    {&quot;vertex&quot; : v3, &quot;weight&quot; : 5}
);
v3.appendNeighbor(
    {&quot;vertex&quot; : v2, &quot;weight&quot; : 5},
    {&quot;vertex&quot; : v4, &quot;weight&quot; : 7},
    {&quot;vertex&quot; : v0, &quot;weight&quot; : 8}
);
v4.appendNeighbor(
    {&quot;vertex&quot; : v2, &quot;weight&quot; : 1},
    {&quot;vertex&quot; : v3, &quot;weight&quot; : 7},
    {&quot;vertex&quot; : v0, &quot;weight&quot; : 4}
);
var V = [v0, v1, v2, v3, v4];

// initialize
var key  = [];
var pred = [];
for(var i = 0; i &lt; V.length; i++){
    key[V[i]['value']]  = Number.POSITIVE_INFINITY;
    pred[V[i]['value']] = -1;
}
key[0] = 0;// 任意の1頂点をスタート地点とするため優先度を0にする
var bh = new BinaryHeap();
for(var i = 0; i &lt; V.length; i++){
    // 頂点を優先度付きキューに格納
    bh.insert(V[i], key[V[i]['value']]);
}

// calc
while(bh.getList().length &gt; 0){
    var u = bh.getPrior();// 優先度で先頭にくる頂点を取り出す
    for(var i = 0; i &lt; u['neighbor'].length; i++){// 経路が存在している頂点でループ
        var neighbor = u['neighbor'][i]['vertex'];
        // 頂点(a)がキューに存在している場合
        if(bh.inQueue(neighbor)){
            var weight = u['neighbor'][i]['weight'];
            // かつ頂点(a)まで距離が前回のループまでに到達した距離よりも短い場合
            if(weight &lt; key[neighbor['value']]){
                pred[neighbor['value']] = u['value'];// 頂点を配列に格納
                key[neighbor['value']]  = weight;// 距離を配列に格納
                bh.changePriority(neighbor, weight);// 優先度を更新（キューの先頭に近づく）
            }
        }
    }
}

// result
console.log(&quot;key:&quot;);
console.log(key);
console.log(&quot;pred:&quot;);
console.log(pred);
</pre>
<h4>結果</h4>
<p>最小全域木の距離の総和は以下を足した値となる。</p>
<table>
<tbody>
<tr>
<td>0</td>
<td>2</td>
<td>3</td>
<td>5</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>計算時に辿った経路は以下のようになる。</p>
<table>
<tbody>
<tr>
<td>-1</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>2</td>
</tr>
</tbody>
</table>
<section class="kakomi">
<h4>優先度付きキュー</h4>
<p><a href="/?p=3673">以前の記事</a>で使用したコードにメソッドを追記して使用した。</p>
<pre class="brush: jscript;">
/**
 * BinaryHeap
 */
var BinaryHeap = function(){
    var self = this;
    self._ary  = [];
}
BinaryHeap.prototype._build = function(){
    var self = this;
    /**
     * heapify
     * 3要素を比較し最も小さい要素を親とする
     * @param {array} ary
     * @param {int} i
     * @param {max} max
     */
    var heapify = function(ary, i, max){
        /**
         * swap
         * @param {array} ary
         * @param {int} x
         * @param {int} y
         */
        var swap = function(ary, x, y){
            var a = ary[x];
            var b = ary[y];
            ary[x] = b;
            ary[y] = a;
            return true;
        }

        var l = 2 * i + 1;
        var r = 2 * i + 2;
        var li = 0;
        if(l &lt; max &amp;&amp; ary[l].priority &lt; ary[i].priority){
            li = l;
        }
        else{
            li = i;
        }
        if(r &lt; max &amp;&amp; ary[r].priority &lt; ary[li].priority){
            li = r;
        }
        if(li !== i){
            swap(ary, i, li);
            heapify(ary, li, max);
        }
    }
    var ary = self._ary;
    for(var i = ary.length - 1; i &gt;= 0; i--){
        heapify(ary, i, self._ary.length);
    }
}
/**
 * BinaryHeap::insert
 * 要素をヒープに追加する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.insert = function(elm, priority){
    var self = this;
    self._ary.push({
        &quot;priority&quot; : priority,
        &quot;elm&quot;      : elm
    });
    self._build();
}
/**
 * BinaryHeap::changePriority
 * 要素の優先度を変更する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.changePriority = function(elm, priority){
    var self = this;
    var ary  = self._ary;
    for(var i = 0; i &lt; ary.length; i++){
        if(elm === ary[i][&quot;elm&quot;]){
            ary[i][&quot;priority&quot;] = priority;
            self._build();
            return true;
        }
    }
    return false;
}
/**
 * BinaryHeap::getPrior
 * 優先度の高い要素を取得する
 */
BinaryHeap.prototype.getPrior = function(){
    var self = this;
    var elm  = self._ary.shift();
    self._build();
    return elm[&quot;elm&quot;];
}
/**
 * BinaryHeap::getList
 * ヒープを返す
 */
BinaryHeap.prototype.getList = function(){
    var self = this;
    return self._ary;
}

/**
 * BinaryHeap::inQueue
 * ヒープ内で探索
 */
BinaryHeap.prototype.inQueue = function(v){
    var self = this;
    for(var i = 0; i &lt; self._ary.length; i++){
        if(self._ary[i]['elm'] === v){
            return true;
        }
    }
    return false;
}
</pre>
<p>inQueueメッソドを効率よくできないかな・・・(●´⌓`●)</p>
</section>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/06/13/javascript%e3%81%a7%e3%83%97%e3%83%aa%e3%83%a0%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptでフロイドワーシャル法</title>
		<link>http://blog.justoneplanet.info/2011/06/05/javascript%e3%81%a7%e3%83%95%e3%83%ad%e3%82%a4%e3%83%89%e3%83%af%e3%83%bc%e3%82%b7%e3%83%a3%e3%83%ab%e6%b3%95/</link>
		<comments>http://blog.justoneplanet.info/2011/06/05/javascript%e3%81%a7%e3%83%95%e3%83%ad%e3%82%a4%e3%83%89%e3%83%af%e3%83%bc%e3%82%b7%e3%83%a3%e3%83%ab%e6%b3%95/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 04:20:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=4051</guid>
		<description><![CDATA[■実装 以下のように実装した。 //Graph var vertexes = [ [null, 2, null, null, 4],// vertex 1 [null, null, 3, null, null],// v [...]]]></description>
			<content:encoded><![CDATA[<h3>■実装</h3>
<p>以下のように実装した。</p>
<pre class="brush: jscript;">
//Graph
var vertexes = [
     [null, 2,    null, null, 4],//    vertex 1
     [null, null, 3,    null, null],// vertex 2
     [null, null, null, 5,    1],//    vertex 3
     [8,    null, null, null, null],// vertex 4
     [null, null, null, 4,    null]//  vertex 5
];

// initialize
var dist = [];
var pred = [];
var n    = vertexes.length;
for(var u = 0; u &lt; n; u++){
    dist[u] = [];
    pred[u] = [];
    for(var i = 0; i &lt; n; i++){
        dist[u][i] = Number.POSITIVE_INFINITY;// 経路が存在しない場合は無限
        pred[u][i] = -1;
        if(vertexes[u][i] !== null){
            dist[u][i] = vertexes[u][i];// 元グラフの経路を代入
            pred[u][i] = u;
        }
    }
    dist[u][u] = 0;// 自身に対しては0の距離が存在する
}
console.log('dist:');
console.log(dist);//...(a)

// 計算
for(var k = 0; k &lt; n; k++){
    for(var i = 0; i &lt; n; i++){
        if(dist[i][k] === Number.POSITIVE_INFINITY){
            continue;
        }
        // 任意の頂点まで有限の距離が開いているとき
        // 有限距離 を経由した任意の頂点を選択し
        // そこまでの距離が既に計算したものよりも小さい場合に
        // その値で上書きする
        for(var j = 0; j &lt; n; j++){
            var newLength = dist[i][k];// ik
            newLength += dist[k][j];
            if(newLength &lt; dist[i][j]){
                dist[i][j] = newLength;
                pred[i][j] = pred[k][j];
            }
        }
    }
}

// 結果
console.log(&quot;dist:&quot;);
console.log(dist);//...(b)
</pre>
<p>(a)の時、distは以下のようになる。</p>
<table border="1" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>0</td>
<td>2</td>
<td>Infinity</td>
<td>Infinity</td>
<td>4</td>
</tr>
<tr>
<td>Infinity</td>
<td>0</td>
<td>3</td>
<td>Infinity</td>
<td>Infinity</td>
</tr>
<tr>
<td>Infinity</td>
<td>Infinity</td>
<td>0</td>
<td>5</td>
<td>1</td>
</tr>
<tr>
<td>8</td>
<td>Infinity</td>
<td>Infinity</td>
<td>0</td>
<td>Infinity</td>
</tr>
<tr>
<td>Infinity</td>
<td>Infinity</td>
<td>Infinity</td>
<td>4</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>殆ど元グラフと変わらない。結果(b)は、以下のようになる。</p>
<table border="1" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>0</td>
<td>2</td>
<td>5</td>
<td>8</td>
<td>4</td>
</tr>
<tr>
<td>16</td>
<td>0</td>
<td>3</td>
<td>8</td>
<td>4</td>
</tr>
<tr>
<td>13</td>
<td>15</td>
<td>0</td>
<td>5</td>
<td>1</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
<td>13</td>
<td>0</td>
<td>12</td>
</tr>
<tr>
<td>12</td>
<td>14</td>
<td>17</td>
<td>4</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>例えば0→1は距離が2、0→2は距離が5、0→3は距離が8、0→4は距離が4であり、1→0は距離が16である。</p>
<h4>経路</h4>
<p>終了時のpredは以下のようになる。</p>
<table border="1" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>-1</td>
<td>0</td>
<td>1</td>
<td>4</td>
<td>0</td>
</tr>
<tr>
<td>3</td>
<td>-1</td>
<td>1</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>0</td>
<td>-1</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>0</td>
<td>1</td>
<td>-1</td>
<td>0</td>
</tr>
<tr>
<td>3</td>
<td>0</td>
<td>1</td>
<td>4</td>
<td>-1</td>
</tr>
</tbody>
</table>
<p>例えば0→1の一つ前の頂点は始点0、0→2の一つ前の頂点は頂点1、0→3の一つ前の頂点は頂点4、0→4の一つ前の頂点は0であり、1→0の場合は頂点3が終点の一つ前である。</p>
<h3>■おまけ</h3>
<p>ちなみに表は以下のようにして描画した。</p>
<pre class="brush: jscript;">
document.write('&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;');
dist.forEach(function(e1, i1, ary1){
	document.write('&lt;tr&gt;');
	e1.forEach(function(e2, i2, ary2){
		document.write('&lt;td&gt;' + e2 + '&lt;/td&gt;');
	});
	document.write('&lt;/tr&gt;');
});
document.write('&lt;/table&gt;');
</pre>
<p>そろそろJavaScriptでもforEachを使って良い頃だと思う。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/06/05/javascript%e3%81%a7%e3%83%95%e3%83%ad%e3%82%a4%e3%83%89%e3%83%af%e3%83%bc%e3%82%b7%e3%83%a3%e3%83%ab%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptでベルマンフォード法</title>
		<link>http://blog.justoneplanet.info/2011/05/07/javascript%e3%81%a7%e3%83%99%e3%83%ab%e3%83%9e%e3%83%b3%e3%83%95%e3%82%a9%e3%83%bc%e3%83%89%e6%b3%95/</link>
		<comments>http://blog.justoneplanet.info/2011/05/07/javascript%e3%81%a7%e3%83%99%e3%83%ab%e3%83%9e%e3%83%b3%e3%83%95%e3%82%a9%e3%83%bc%e3%83%89%e6%b3%95/#comments</comments>
		<pubDate>Fri, 06 May 2011 17:29:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3996</guid>
		<description><![CDATA[■実装 グラフは以下のようにして実装した。グラフは前回のものと同様だがベルマンフォード法では負の重みも存在しうるので、経路が存在しない部分はnullとした。 // Graph //前回のグラフと同じグラフを使用 var  [...]]]></description>
			<content:encoded><![CDATA[<h3>■実装</h3>
<p>グラフは以下のようにして実装した。グラフは前回のものと同様だがベルマンフォード法では負の重みも存在しうるので、経路が存在しない部分はnullとした。</p>
<pre class="brush: jscript;">
// Graph //前回のグラフと同じグラフを使用
var vertexes = [
     [null, 1,    3,    null, null, null],// vertex s
     [null, null, 1,    4,    null, null],// vertex 1
     [null, null, null, 1,    null, null],// vertex 2
     [null, null, null, null, 1,    10],//   vertex 3
     [null, null, null, null, null, 1],//    vertex 4
     [null, null, null, null, null, null] // vertex g
];

// initialize
var dist    = [];
var pred    = [];
for(var i = 0; i &lt; vertexes.length; i++){
    dist[i] = Number.POSITIVE_INFINITY;
    pred[i] = -1;
}
dist[0] = 0;// start

// 計算
(function(){
    var n = vertexes.length;
    for(var i = 1; i &lt;= n; i++){
        // i=nの時
        // destinationと自身が同じであるにも関わらず
        // 後述のnewLenの方が短い場合、
        // 負の閉路が存在していることを示す
        failOnUpdate = (i === n);
        leaveEarly   = true;
        for(var u = 0; u &lt; n; u++){
            for(var ci = 0; ci &lt; n; ci++){
                if(vertexes[u][ci] === null){continue;}//経路が存在しない
                var newLen = dist[u] + vertexes[u][ci];//頂点uを経由したciへの距離
                if(newLen &lt; dist[ci]){// 頂点u経由の方が短い場合はアップデートする
                    if(failOnUpdate){
                        throw new Error('Graph has negative cycle');
                    }
                    dist[ci] = newLen;
                    pred[ci] = u;
                    leaveEarly = false;
                }
            }
        }
        if(leaveEarly){
            break;
        }
    }
})();

// 結果表示
console.log(&quot;最短経路&quot;);
console.log(pred);// [-1, 0, 1, 2, 3, 4]
console.log(&quot;最短距離&quot;);
console.log(dist);// [0, 1, 2, 3, 4, 5]
</pre>
<p>但し、上述の場合では負の重みが存在しない。</p>
<h4>負の重み</h4>
<p>従って以下のデータでテストしてみる。</p>
<pre class="brush: jscript;">
var vertexes = [
     [null, 1,    3,    null, null, null],// s
     [null, null, 1,    4,    null, null],// 1
     [null, null, null, 1,    null, null],// 2
     [null, null, null, null, 1,    -10],// 3
     [null, null, null, null, null, 1],// 4
     [null, null, null, null, null, null] // g
];
</pre>
<p>以下のような結果となる。</p>
<pre class="brush: jscript;">
console.log(&quot;最短経路&quot;);
console.log(pred);// [-1, 0, 1, 2, 3, 3]
console.log(&quot;最短距離&quot;);
console.log(dist);// [0, 1, 2, 3, 4, -7]
</pre>
<p>3→gの距離が4を経由するよりも近くなり、s〜gの重みは-7となった。</p>
<h4>負の閉路</h4>
<p>以下のように閉路（ループ）で総和が負の値になるような経路を用意する。</p>
<pre class="brush: jscript;">
var vertexes = [
     [null, -1,   3,    null, null, null],// s
     [null, null, -10,  4,    null, null],// 1
     [5,    null, null, 1,    null, null],// 2
     [null, null, null, null, 1,    -10],// 3
     [null, null, null, null, null, 1],// 4
     [null, null, null, null, null, null] // g
];
</pre>
<p>以下のようなエラーが発生する。</p>
<pre class="brush: jscript;">
//Uncaught Error: Graph has negative cycle
</pre>
<p>ベルマンフォード法は負の重みがあった場合でも処理が可能であるが、総和が0より小さい負の閉路が存在していた場合は使用できない。但し、そのような場合は最短経路自体が意味を成さない。ちなみに密グラフには向かないアルゴリズムであるので、多次元配列（行列）でのグラフ生成は良くないかもしれない。(●´⌓`●)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/05/07/javascript%e3%81%a7%e3%83%99%e3%83%ab%e3%83%9e%e3%83%b3%e3%83%95%e3%82%a9%e3%83%bc%e3%83%89%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3Dにおける頂点と行列</title>
		<link>http://blog.justoneplanet.info/2011/05/03/3d%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e9%a0%82%e7%82%b9%e3%81%a8%e8%a1%8c%e5%88%97/</link>
		<comments>http://blog.justoneplanet.info/2011/05/03/3d%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e9%a0%82%e7%82%b9%e3%81%a8%e8%a1%8c%e5%88%97/#comments</comments>
		<pubDate>Mon, 02 May 2011 15:26:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[コンピューター]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=4259</guid>
		<description><![CDATA[頂点を表すベクトルに対して乗算する事で以下のような操作ができる行列である。 ■移動行列 1, 0, 0, 1 0, 1, 0, 0 0, 0, 1, 0 dx, dy, dz, 1 ■拡大縮小行列 zx, 0, 0, 0 [...]]]></description>
			<content:encoded><![CDATA[<p>頂点を表すベクトルに対して乗算する事で以下のような操作ができる行列である。</p>
<h3>■移動行列</h3>
<pre class="brush: xml;">
 1,  0,  0, 1
 0,  1,  0, 0
 0,  0,  1, 0
dx, dy, dz, 1
</pre>
<h3>■拡大縮小行列</h3>
<pre class="brush: xml;">
zx,  0,  0, 0
 0, zy,  0, 0
 0,  0, zz, 0
 0,  0,  0, 1
</pre>
<h3>■回転行列</h3>
<pre class="brush: xml;">
XX(1 - cosθ) +  cosθ,  XY(1- cosθ) - Zsinθ,  XZ(1 - cosθ) + Ysinθ, 0
XY(1 - cosθ) + Zsinθ,  YY(1- cosθ) -  cosθ,  YZ(1 - cosθ) + Xsinθ, 0
XZ(1 - cosθ) + Ysinθ,  ZY(1- cosθ) + Xsinθ,  ZZ(1 - cosθ) +  cosθ, 0
                   0,                    0,                     0, 1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/05/03/3d%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e9%a0%82%e7%82%b9%e3%81%a8%e8%a1%8c%e5%88%97/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptでダイクストラ法（行列）</title>
		<link>http://blog.justoneplanet.info/2011/01/14/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95%ef%bc%88%e8%a1%8c%e5%88%97%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2011/01/14/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95%ef%bc%88%e8%a1%8c%e5%88%97%ef%bc%89/#comments</comments>
		<pubDate>Thu, 13 Jan 2011 21:48:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3697</guid>
		<description><![CDATA[前回の記事では、生成するグラフが疎であったので連結リストを使用した。密グラフ向けに行列でも実装した。 ■実装 // Graph //（密ではないが）前回のグラフと同じグラフを使用 var Vertexes = [ [0, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/?p=3678">前回の記事</a>では、生成するグラフが疎であったので連結リストを使用した。密グラフ向けに行列でも実装した。</p>
<h3>■実装</h3>
<pre class="brush: jscript;">
// Graph //（密ではないが）前回のグラフと同じグラフを使用
var Vertexes = [
             [0, 1, 3, 0, 0, 0],// s
             [0, 0, 1, 4, 0, 0],// 1
             [0, 0, 0, 1, 0, 0],// 2
             [0, 0, 0, 0, 1,10],// 3
             [0, 0, 0, 0, 0, 1],// 4
             [0, 0, 0, 0, 0, 0] // g
];

// initialize
var dist    = [];
var pred    = [];
var visited = [];
for(var i = 0; i &lt; Vertexes.length; i++){
    dist[i] = Number.POSITIVE_INFINITY;
    pred[i] = -1;
    visited[i] = false;// 訪問を記録する
}
dist[0] = 0;// start

// search
var dijkstraMX = function(){
    var getMin = function(){
        var tmp = Number.POSITIVE_INFINITY;
        for(var i = 0; i &lt; Vertexes.length; i++){
            if(visited[i] === false &amp;&amp; dist[i] &lt; tmp){
                tmp = i;
            }
        }
        if(tmp === Number.POSITIVE_INFINITY){
            tmp = null;
        }
        return tmp;
    }

    while(true){
        var u = getMin();// 未訪問の中でスタートから最小の距離の頂点
        // 「sから辿れない頂点しか残っていない場合」「未訪問が無い場合」はループ終了
        if(dist[u] === Number.POSITIVE_INFINITY || u === null){break;}
        visited[u] = true;
        for(var i = 0; i &lt; Vertexes[u].length; i++){
            if(Vertexes[u][i] &gt; 0){// 辺が存在している
                var neighbor  = i;//隣接点(a)
                var weight    = Vertexes[u][i];// (a)との辺の重み
                var newLength = dist[u] + weight;// (b)
                // 現在セットされている、スタート地点から隣接点までの距離が
                // 新しい経路での値より大きい時
                if(newLength &lt; dist[neighbor]){
                    dist[neighbor] = newLength;
                    pred[neighbor] = u;
                }
            }
        }
    }
}
dijkstraMX();

// 最短経路
console.log(pred);// [-1, 0, 1, 2, 3, 4]

// 最短距離
console.log(dist);// [0, 1, 2, 3, 4, 5]
</pre>
<p>グラフが疎である場合、行列を使用すると殆どの空間が0で埋められるので勿体無いね。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/14/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95%ef%bc%88%e8%a1%8c%e5%88%97%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScriptでダイクストラ法</title>
		<link>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95/</link>
		<comments>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95/#comments</comments>
		<pubDate>Tue, 11 Jan 2011 17:15:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3678</guid>
		<description><![CDATA[優先度つきキューを使用したダイクストラ法をJavaScriptで実装した。 ■実装 /** * Vertex * @param int value */ var Vertex = function(value){ var [...]]]></description>
			<content:encoded><![CDATA[<p>優先度つきキューを使用したダイクストラ法をJavaScriptで実装した。</p>
<h3>■実装</h3>
<pre class="brush: jscript;">
/**
 * Vertex
 * @param int value
 */
var Vertex = function(value){
    var self = this;
    self.value    = value;
    self.state    = 0;
    self.dist     = Number.POSITIVE_INFINITY;// もしくは十分に大きい値とか
    self.neighbor = [];
    self.appendNeighbor = function(){
        for(var i = 0; i &lt; arguments.length; i++){
            self.neighbor.push(arguments[i]);
        }
    }
}

// set up a graph
var s  = new Vertex(0);
var v1 = new Vertex(1);
var v2 = new Vertex(2);
var v3 = new Vertex(3);
var v4 = new Vertex(4);
var g  = new Vertex(5);

// set up connections
// 単純化のためループや往路を除去した
s.appendNeighbor(
    {&quot;weight&quot; : 1, &quot;vertex&quot; : v1},
    {&quot;weight&quot; : 3, &quot;vertex&quot; : v2}
);
v1.appendNeighbor(
    {&quot;weight&quot; : 1, &quot;vertex&quot; : v2},
    {&quot;weight&quot; : 4, &quot;vertex&quot; : v3}
);
v2.appendNeighbor(
    {&quot;weight&quot; : 1, &quot;vertex&quot; : v3}
);
v3.appendNeighbor(
    {&quot;weight&quot; : 1, &quot;vertex&quot; : v4},
    {&quot;weight&quot; : 10, &quot;vertex&quot; : g}
);
v4.appendNeighbor(
    {&quot;weight&quot; : 1, &quot;vertex&quot; : g}
);
g.appendNeighbor(
);

// initialize
var vertexes = [s, v1, v2, v3, v4, g];
var pred     = [];
var pq       = new BinaryHeap();// sからの距離が短い頂点順の優先度つきキュー
s.dist = 0;
for(var i = 0; i &lt; vertexes.length; i++){// キューの生成
    pred[i] = -1;
    pq.insert(vertexes[i], vertexes[i].dist);
}

// search
var dijkstraPQ = function(){
    while(pq.getList().length &gt; 0){
        var u = pq.getPrior();// スタートからの距離が近い頂点を取得しcurrent頂点とする
        for(var i = 0; i &lt; u.neighbor.length; i++){
            var neighbor  = u.neighbor[i].vertex;
            var weight    = u.neighbor[i].weight;// 隣接点の距離...(a)
            var newLength = u.dist + weight;// current頂点のsからの距離と(a)を加算...(b)
            // (b) &lt; visitした時の距離の場合
            // キューを更新し、最短経路も更新する
            if(newLength &lt; neighbor.dist){
                pq.changePriority(neighbor, newLength);
                neighbor.dist = newLength;
                pred[neighbor.value] = u.value;
            }
        }
    }
}
dijkstraPQ();

// 最短経路
console.log(pred);// [-1, 0, 1, 2, 3, 4]
// g&lt;-v4&lt;-v3-&lt;v2&lt;-v1&lt;-s

// 最短距離
console.log(g.dist);// 5
</pre>
<p>任意の頂点に対して一つ前の頂点とその時の距離が分かる。</p>
<h3>■特性</h3>
<ul>
<li>辺の重みは0より大きい値</li>
<li>重みの和が0より小さい閉路が存在すると無限ループする可能性がある</li>
</ul>
<section class="kakomi">
<h4>優先度つきキューについて</h4>
<p><a href="/?p=3673">前回の記事</a>のコードをそのまま使用した。</p>
<pre class="brush: jscript;">
/**
 * BinaryHeap
 */
var BinaryHeap = function(){
    var self = this;
    self._ary  = [];
}
BinaryHeap.prototype._build = function(){
    var self = this;
    /**
     * heapify
     * 3要素を比較し最も小さい要素を親とする
     * @param {array} ary
     * @param {int} i
     * @param {max} max
     */
    var heapify = function(ary, i, max){
        /**
         * swap
         * @param {array} ary
         * @param {int} x
         * @param {int} y
         */
        var swap = function(ary, x, y){
            var a = ary[x];
            var b = ary[y];
            ary[x] = b;
            ary[y] = a;
            return true;
        }

        var l = 2 * i + 1;
        var r = 2 * i + 2;
        var li = 0;
        if(l &lt; max &amp;&amp; ary[l].priority &lt; ary[i].priority){
            li = l;
        }
        else{
            li = i;
        }
        if(r &lt; max &amp;&amp; ary[r].priority &lt; ary[li].priority){
            li = r;
        }
        if(li !== i){
            swap(ary, i, li);
            heapify(ary, li, max);
        }
    }
    var ary = self._ary;
    for(var i = ary.length - 1; i &gt;= 0; i--){
        heapify(ary, i, self._ary.length);
    }
}
/**
 * BinaryHeap::insert
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.insert = function(elm, priority){
    var self = this;
    self._ary.push({
        &quot;priority&quot; : priority,
        &quot;elm&quot;      : elm
    });
    self._build();
}
/**
 * BinaryHeap::changePriority
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.changePriority = function(elm, priority){
    var self = this;
    var ary  = self._ary;
    for(var i = 0; i &lt; ary.length; i++){
        if(elm === ary[i][&quot;elm&quot;]){
            ary[i][&quot;priority&quot;] = priority;
            self._build();
            return true;
        }
    }
    return false;
}
/**
 * BinaryHeap::getPrior
 */
BinaryHeap.prototype.getPrior = function(){
    var self = this;
    var elm  = self._ary.shift();
    self._build();
    return elm[&quot;elm&quot;];
}
/**
 * BinaryHeap::getList
 */
BinaryHeap.prototype.getList = function(){
    var self = this;
    return self._ary;
}
</pre>
</section>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e3%83%80%e3%82%a4%e3%82%af%e3%82%b9%e3%83%88%e3%83%a9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptで二分ヒープ（優先度つきキュー）</title>
		<link>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e3%83%92%e3%83%bc%e3%83%97%ef%bc%88%e5%84%aa%e5%85%88%e5%ba%a6%e3%81%a4%e3%81%8d%e3%82%ad%e3%83%a5%e3%83%bc%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e3%83%92%e3%83%bc%e3%83%97%ef%bc%88%e5%84%aa%e5%85%88%e5%ba%a6%e3%81%a4%e3%81%8d%e3%82%ad%e3%83%a5%e3%83%bc%ef%bc%89/#comments</comments>
		<pubDate>Tue, 11 Jan 2011 16:43:52 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3673</guid>
		<description><![CDATA[Cの場合は以下のようにして、二分ヒープを使用することができるらしい。 #include &#34;BinaryHeap.h&#34; ■実装 しかし、JavaScriptには二分ヒープのようなデータ構造が存在しないの [...]]]></description>
			<content:encoded><![CDATA[<p>Cの場合は以下のようにして、二分ヒープを使用することができるらしい。</p>
<pre class="brush: cpp;">
#include &quot;BinaryHeap.h&quot;
</pre>
<h3>■実装</h3>
<p>しかし、JavaScriptには二分ヒープのようなデータ構造が存在しないので、以下のように自力で実装する。</p>
<pre class="brush: jscript;">
/**
 * BinaryHeap
 */
var BinaryHeap = function(){
    var self = this;
    self._ary  = [];
}
BinaryHeap.prototype._build = function(){
    var self = this;
    /**
     * heapify
     * 3要素を比較し最も小さい要素を親とする
     * @param {array} ary
     * @param {int} i
     * @param {max} max
     */
    var heapify = function(ary, i, max){
        /**
         * swap
         * @param {array} ary
         * @param {int} x
         * @param {int} y
         */
        var swap = function(ary, x, y){
            var a = ary[x];
            var b = ary[y];
            ary[x] = b;
            ary[y] = a;
            return true;
        }

        var l = 2 * i + 1;
        var r = 2 * i + 2;
        var li = 0;
        if(l &lt; max &amp;&amp; ary[l].priority &lt; ary[i].priority){
            li = l;
        }
        else{
            li = i;
        }
        if(r &lt; max &amp;&amp; ary[r].priority &lt; ary[li].priority){
            li = r;
        }
        if(li !== i){
            swap(ary, i, li);
            heapify(ary, li, max);
        }
    }
    var ary = self._ary;
    for(var i = ary.length - 1; i &gt;= 0; i--){
        heapify(ary, i, self._ary.length);
    }
}
/**
 * BinaryHeap::insert
 * 要素をヒープに追加する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.insert = function(elm, priority){
    var self = this;
    self._ary.push({
        &quot;priority&quot; : priority,
        &quot;elm&quot;      : elm
    });
    self._build();
}
/**
 * BinaryHeap::changePriority
 * 要素の優先度を変更する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.changePriority = function(elm, priority){
    var self = this;
    var ary  = self._ary;
    for(var i = 0; i &lt; ary.length; i++){
        if(elm === ary[i][&quot;elm&quot;]){
            ary[i][&quot;priority&quot;] = priority;
            self._build();
            return true;
        }
    }
    return false;
}
/**
 * BinaryHeap::getPrior
 * 優先度の高い要素を取得する
 */
BinaryHeap.prototype.getPrior = function(){
    var self = this;
    var elm  = self._ary.shift();
    self._build();
    return elm[&quot;elm&quot;];
}
/**
 * BinaryHeap::getList
 * ヒープを返す
 */
BinaryHeap.prototype.getList = function(){
    var self = this;
    return self._ary;
}

// test code
var pq = new BinaryHeap();
pq.insert('pochi', 0);
pq.insert('son', 4);
pq.insert('mike', 10);
pq.insert('father', 1);
pq.insert('mother', 2);
console.log(pq.getList());
</pre>
<p>優先度つきキューに使用したいので、<a href="/?p=3472">ヒープソートのコード</a>を変更し最小ヒープとした。使用方法は以下のとおりである。</p>
<h4>二分ヒープの生成</h4>
<pre class="brush: jscript;">
var pq = new BinaryHeap();
</pre>
<h4>要素の追加</h4>
<pre class="brush: jscript;">
pq.insert(elm, priority);
</pre>
<h4>優先度の変更</h4>
<pre class="brush: jscript;">
pq.changePriority(elm, priority);
</pre>
<h4>最優先要素の取得</h4>
<pre class="brush: jscript;">
var elm = pq.getPrior();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/12/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e3%83%92%e3%83%bc%e3%83%97%ef%bc%88%e5%84%aa%e5%85%88%e5%ba%a6%e3%81%a4%e3%81%8d%e3%82%ad%e3%83%a5%e3%83%bc%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptで幅優先探索</title>
		<link>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e5%b9%85%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/</link>
		<comments>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e5%b9%85%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/#comments</comments>
		<pubDate>Mon, 10 Jan 2011 13:00:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3661</guid>
		<description><![CDATA[/** * Vertex * @param int value */ var Vertex = function(value){ var self = this; self.value = value; self.sta [...]]]></description>
			<content:encoded><![CDATA[<pre class="brush: jscript;">
/**
 * Vertex
 * @param int value
 */
var Vertex = function(value){
    var self = this;
    self.value    = value;
    self.state    = 0;
    self.neighbor = [];
    self.appendNeighbor = function(){
        for(var i = 0; i &lt; arguments.length; i++){
            self.neighbor.push(arguments[i]);
        }
    }
}

// set up a graph
var s  = new Vertex(0);
var v1 = new Vertex(1);
var v2 = new Vertex(2);
var v3 = new Vertex(3);
var v4 = new Vertex(4);
var v5 = new Vertex(5);
var v6 = new Vertex(6);
var v7 = new Vertex(7);
var v8 = new Vertex(8);
var g  = new Vertex(9);
s.appendNeighbor(v1, v4);
v1.appendNeighbor(s, v2);
v2.appendNeighbor(v1, v3);
v3.appendNeighbor(v2, v4, g);
v4.appendNeighbor(v3, v5, s);
v5.appendNeighbor(v4);
v6.appendNeighbor(v7);
v7.appendNeighbor(v6);
g.appendNeighbor(v3);
var vertexes = [s, v1, v2, v3, v4, v5, v6, v7, v8, g];

// initialize
var pred       = [];
var distance   = [];
var queue = [];
var counter    = 0;
for(var i = 0; i &lt; vertexes.length; i++){
    pred[vertexes[i].value]       = -1;
    distance[vertexes[i].value]   = -1;
}

// search
s.state = 1;
distance[s.value] = 0;
queue.push(s);
var breadthFirstSearch = function(){
    while(queue.length &gt; 0){
        var vertex = queue.shift();// 処理する頂点
        for(var i = 0; i &lt; vertex.neighbor.length; i++){// 隣接点全てに対して
            var n = vertex.neighbor[i];
            if(vertex.neighbor[i].state === 0){
                distance[n.value] = distance[vertex.value] + 1;// 処理中の頂点+1の距離
                pred[n.value]     = vertex.value;// 処理中の頂点の値
                n.state           = 1;// visitした記録
                queue.push(n);// 隣接点をキューに入れる
            }
        }
        vertex.state = 2;// 処理し終わった記録
    }
}
breadthFirstSearch();

// 1つ前の節点の値
console.log(pred);// [-1, 0, 1, 4, 0, 4, -1, -1, -1, 3]

// 各節点のスタートからの距離
console.log(distance);// [0, 1, 2, 2, 1, 2, -1, -1, -1, 3]

console.log(vertexes);
</pre>
<p>スタート地点から全体に探索菌が同速度で広がっていくイメージだね。</p>
<h3>■特性</h3>
<ul>
<li>無向グラフでも有向グラフでも機能する</li>
<li>重みでなくステップ数での最短距離を求めることができる</li>
<li>節点をQueueに蓄えるので巨大グラフでは巨大なストレージが必要となる</li>
<li>スタートから辿れない頂点は基本的には訪問しない</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e5%b9%85%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptで深さ優先探索</title>
		<link>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e6%b7%b1%e3%81%95%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/</link>
		<comments>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e6%b7%b1%e3%81%95%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/#comments</comments>
		<pubDate>Mon, 10 Jan 2011 12:07:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[グラフ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3654</guid>
		<description><![CDATA[■実装 /** * Vertex * @param int value */ var Vertex = function(value){ var self = this; self.value = value; self [...]]]></description>
			<content:encoded><![CDATA[<h3>■実装</h3>
<pre class="brush: jscript;">
/**
 * Vertex
 * @param int value
 */
var Vertex = function(value){
    var self = this;
    self.value    = value;
    self.state    = 0;
    self.neighbor = [];
    self.appendNeighbor = function(){
        for(var i = 0; i &lt; arguments.length; i++){
            self.neighbor.push(arguments[i]);
        }
    }
}

// set up a graph
var s  = new Vertex(0);
var v1 = new Vertex(1);
var v2 = new Vertex(2);
var v3 = new Vertex(3);
var v4 = new Vertex(4);
var v5 = new Vertex(5);
var v6 = new Vertex(6);
var v7 = new Vertex(7);
var v8 = new Vertex(8);
var g  = new Vertex(9);

// set up connections
s.appendNeighbor(v1, v4);
v1.appendNeighbor(s, v2);
v2.appendNeighbor(v1, v3);
v3.appendNeighbor(v2, v4, g);
v4.appendNeighbor(v3, v5, s);
v5.appendNeighbor(v4);
v6.appendNeighbor(v7);
v7.appendNeighbor(v6);
g.appendNeighbor(v3);
var vertexes = [s, v1, v2, v3, v4, v5, v6, v7, v8, g];

// initialize
var pred       = [];
var discovered = [];
var finished   = [];
var counter    = 0;
for(var i = 0; i &lt; vertexes.length; i++){
    pred[vertexes[i].value]       = -1;
    discovered[vertexes[i].value] = -1;
    finished[vertexes[i].value]   = -1;
}

/**
 * depthFirstSearch
 * @param array vertexes
 */
var depthFirstSearch = function(vertexes){
    depthFirstVisit(s);// start地点から探索
    // 以下の処理でstart地点から辿れない頂点を探索
    for(var i = 0; i &lt; vertexes.length; i++){
        if(vertexes[i].state === 0){
            depthFirstVisit(vertexes[i]);
        }
    }
} 

/**
 * depthFirstVisit
 * @param Vertex vertex
 */
var depthFirstVisit = function(vertex){
    vertex.state = 1;// 探索した事を記録（再帰処理部分で自身を再訪しないように）
    discovered[vertex] = ++counter;
    // 以下の処理で隣接点を探索
    for(var i = 0; i &lt; vertex.neighbor.length; i++){
        if(vertex.neighbor[i].state === 0){
            pred[vertex.neighbor[i].value] = vertex.value;
            depthFirstVisit(vertex.neighbor[i]);
        }
    }
    vertex.state = 2;// 全ての隣接点を探索した事を記録
    finished[vertex.value] = ++counter;
}
depthFirstSearch(vertexes);

// 1つ前の節点の値
console.log(pred);// [-1, 0, 1, 2, 3, 4, -1, 6, -1, 3]
// g&lt;-3(v3)&lt;-2(v2)&lt;-1(v1)&lt;-0(s)

// 発見したときのカウンタの値
console.log(discovered);// [1, 2, 3, 4, 5, 6, 15, 16, 19, 9]

// 探索し終えたときのカウンタの値
console.log(finished);// [14, 13, 12, 11, 8, 7, 18, 17, 20, 10]

console.log(vertexes);
</pre>
<h3>■特性</h3>
<ul>
<li>グラフ全体を見通して経路を生成することはできず、求められる経路は最短経路ではない</li>
<li>無向グラフでも有向グラフでも機能する</li>
<li>グラフ探索において情報蓄積量が最小</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/10/javascript%e3%81%a7%e6%b7%b1%e3%81%95%e5%84%aa%e5%85%88%e6%8e%a2%e7%b4%a2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>二分木と二分探索木</title>
		<link>http://blog.justoneplanet.info/2011/01/08/%e4%ba%8c%e5%88%86%e6%9c%a8%e3%81%a8%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/</link>
		<comments>http://blog.justoneplanet.info/2011/01/08/%e4%ba%8c%e5%88%86%e6%9c%a8%e3%81%a8%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 12:57:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[探索]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3633</guid>
		<description><![CDATA[意思の疎通が上手くいかなかったりするので、ちゃんと区別したい。で記事にした。゜(´□｀｡)°゜ ■二分木（binary tree） 各ノードの子要素が2以下で通常は左と右と呼ばれる。 var BT = function( [...]]]></description>
			<content:encoded><![CDATA[<p>意思の疎通が上手くいかなかったりするので、ちゃんと区別したい。で記事にした。゜(´□｀｡)°゜</p>
<h3>■二分木（binary tree）</h3>
<p>各ノードの子要素が2以下で通常は左と右と呼ばれる。</p>
<pre class="brush: jscript;">
var BT = function(value){
    var self = this;
    self._left  = null;
    self._right = null;
    self.value = value;
    self.appendChild = function(child, location){
        if(location === 'left' &amp;&amp; self._left === null){
            self._left = child;
            return true;
        }
        else if(location === 'right' &amp;&amp; self._right === null){
            self._right = child;
            return true;
        }
        else{
            return false;
        }
    }
}

// test code
var root  = new BT(5);
var leaf1 = new BT(7);
var leaf2 = new BT(2);
var leaf3 = new BT(10);
var leaf4 = new BT(6);
var leaf5 = new BT(1);
var leaf6 = new BT(8);

root.appendChild(leaf1, 'left');
root.appendChild(leaf2, 'right');

leaf1.appendChild(leaf3, 'left');
leaf1.appendChild(leaf4, 'right');
leaf2.appendChild(leaf5, 'left');
leaf2.appendChild(leaf6, 'right');

console.log(root);
console.log(JSON.stringify(root));
</pre>
<h3>■二分探索木（binary search tree）</h3>
<p>二分木の一種だが要素の大小に『left &lt; parent &lt; right』という順序が成立する。</p>
<pre class="brush: jscript;">
var BST = function(value){
    var self = this;
    self._left  = null;
    self._right = null;
    self.value = value;
    self.appendChild = function(child){
        if(child.value &lt; self.value){
            if(self._left){
                self._left.appendChild(child);
            }
            else{
                self._left = child;
            }
        }
        else{
            if(self._right){
                self._right.appendChild(child);
            }
            else{
                self._right = child;
            }
        }
    }
}

// test code
var root  = new BST(5);
var leaf1 = new BST(7);
var leaf2 = new BST(2);
var leaf3 = new BST(10);
var leaf4 = new BST(6);
var leaf5 = new BST(1);
var leaf6 = new BST(8);

root.appendChild(leaf1);
root.appendChild(leaf2);
root.appendChild(leaf3);
root.appendChild(leaf4);
root.appendChild(leaf5);
root.appendChild(leaf6);

console.log(root);
console.log(JSON.stringify(root));
</pre>
<p>つまり要素の大小関係に基づいて位置が決まるのがbinary search treeであって、binary treeではないよね。ちなみに以前はめんどいから<a href="/?p=3588">配列で実装</a>した。配列で実現することも可能だが、木が平衡でない場合に無駄な空きができてしまう。</p>
<h3>■文献</h3>
<p>まぁ、色々読んだほうが早いかもしれん。</p>
<h4><a href="http://en.wikipedia.org/wiki/Binary_tree">Binary tree</a></h4>
<blockquote><p>Binary trees are commonly used to implement binary search trees and binary heaps.</p></blockquote>
<h4><a href="http://en.wikipedia.org/wiki/Binary_search_tree">Binary search tree</a></h4>
<blockquote>
<p>In computer science, a binary search tree (BST) or ordered binary tree is a node-based binary tree data structure which has the following properties:[1]</p>
<ul>
<li>The left subtree of a node contains only nodes with keys less than the node&#8217;s key.</li>
<li>The right subtree of a node contains only nodes with keys greater than the node&#8217;s key.</li>
<li>Both the left and right subtrees must also be binary search trees.</li>
</ul>
</blockquote>
<h4><a href="http://www.amazon.co.jp/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-George-T-Heineman/dp/4873114284">アルゴリズムクイックリファレンス</a>（p143）</h4>
<blockquote><p>二分探索木Tは、順序特性を持つ、すなわちキーによって識別される節点の有限集合となる。節点集合は空でなければ、根節点（root node）n<sub>r</sub>を含む。節点nは、2つの二分探索木T<sub>l</sub>とT<sub>r</sub>とを持ち、節点nのキーをkとしたら、T<sub>l</sub>のすべてのキーが≦kで、T<sub>r</sub>のすべてのキーが≧kであるという性質を保持する。この性質は、<strong>二分探索木の性質</strong>（binary-search-tree property）と呼ばれる（<a href="http://www.amazon.co.jp/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%82%A4%E3%83%B3%E3%83%88%E3%83%AD%E3%83%80%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3-%E7%AC%AC1%E5%B7%BB-%E6%95%B0%E5%AD%A6%E7%9A%84%E5%9F%BA%E7%A4%8E%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-T-%E3%82%B3%E3%83%AB%E3%83%A1%E3%83%B3/dp/4764902451">Cormen et al., 2001</a>）。</p></blockquote>
<h3>■canvas</h3>
<p>つーかさ、console.logで確認するのめんどいよね！そういうわけでcanvasで表示させます。</p>
<pre class="brush: jscript;">
var BST = function(value){
    var self = this;
    self._left  = null;
    self._right = null;
    self.value = value;

    /**
     * appendChild
     * @param {Object} child
     */
    self.appendChild = function(child){
        if(child.value &lt; self.value){
            if(self._left){
                self._left.appendChild(child);
            }
            else{
                self._left = child;
            }
        }
        else{
            if(self._right){
                self._right.appendChild(child);
            }
            else{
                self._right = child;
            }
        }
    }

    /**
     * draw
     * @param {Object} context
     * @param {int} left
     * @param {int} top
     * @param {int} center
     * @param {int} depth
     */
    self.draw = function(context, left, top, center, depth){
        if(self._left !== null){
            var cl = left - (center / Math.pow(2, depth + 1));
            var ct = top + 50
            context.fillStyle = 'black';
            context.beginPath();
            context.moveTo(left, top);
            context.lineTo(cl, ct);
            context.stroke();
            var lp = self._left.draw(context, cl, ct, center, depth + 1);
        }
        if(self._right !== null){
            var cl = left + (center / Math.pow(2, depth + 1));
            var ct = top + 50
            context.fillStyle = 'black';
            context.beginPath();
            context.moveTo(left, top);
            context.lineTo(cl, ct);
            context.stroke();
            var lp = self._right.draw(context, cl, ct, center, depth + 1);
        }
        context.fillStyle = 'red';
        context.beginPath();
        context.arc(left, top, 10, 0, Math.PI * 2, false);
        context.fill();

        context.font = &quot;15px Arial bold&quot;;
        context.textAlign = &quot;center&quot;;
        context.textBaseline = &quot;middle&quot;;
        context.fillStyle = 'white';
        context.fillText(self.value, left, top, 30);
        return {&quot;left&quot; : left, &quot;top&quot; : top};
    }
}

// test code
var root  = new BST(5);
root.appendChild(new BST(7));
root.appendChild(new BST(2));
root.appendChild(new BST(10));
root.appendChild(new BST(6));
root.appendChild(new BST(1));
root.appendChild(new BST(8));
root.appendChild(new BST(12));
root.appendChild(new BST(11));
root.appendChild(new BST(9));
root.appendChild(new BST(4));
root.draw(document.getElementById(&quot;canvas&quot;).getContext('2d'), 200, 50, 200, 0);
</pre>
<p><canvas id="canvas20110108" width="500" height="300"></canvas></p>
<p>おや、まぁ、なんと素敵なことでしょう！(oﾟ▽ﾟ)♡</p>
<p><script type="text/javascript">
jQuery(function(){
var BST = function(value){
    var self = this;
    self._left  = null;
    self._right = null;
    self.value = value;
    /**
     * appendChild
     * @param {Object} child
     */
    self.appendChild = function(child){
        if(child.value < self.value){
            if(self._left){
                self._left.appendChild(child);
            }
            else{
                self._left = child;
            }
        }
        else{
            if(self._right){
                self._right.appendChild(child);
            }
            else{
                self._right = child;
            }
        }
    }
    /**
     * draw
     * @param {Object} context
     * @param {int} left
     * @param {int} top
     * @param {int} center
     * @param {int} depth
     */
    self.draw = function(context, left, top, center, depth){
        if(self._left !== null){
            var cl = left - (center / Math.pow(2, depth + 1));
            var ct = top + 50
            context.fillStyle = 'black';
            context.beginPath();
            context.moveTo(left, top);
            context.lineTo(cl, ct);
            context.stroke();
            var lp = self._left.draw(context, cl, ct, center, depth + 1);
        }
        if(self._right !== null){
            var cl = left + (center / Math.pow(2, depth + 1));
            var ct = top + 50
            context.fillStyle = 'black';
            context.beginPath();
            context.moveTo(left, top);
            context.lineTo(cl, ct);
            context.stroke();
            var lp = self._right.draw(context, cl, ct, center, depth + 1);
        }
        context.beginPath();
        context.fillStyle = 'red';
        context.arc(left, top, 10, 0, Math.PI * 2, false);
        context.fill();
        context.font = "15px Arial bold";
        context.textAlign = "center";
        context.textBaseline = "middle";
        context.fillStyle = 'white';
        context.fillText(self.value, left, top, 30);
        return {"left" : left, "top" : top};
    }
}
var root  = new BST(5);
root.appendChild(new BST(7));
root.appendChild(new BST(2));
root.appendChild(new BST(10));
root.appendChild(new BST(6));
root.appendChild(new BST(1));
root.appendChild(new BST(8));
root.appendChild(new BST(12));
root.appendChild(new BST(11));
root.appendChild(new BST(9));
root.appendChild(new BST(4));
root.draw(document.getElementById("canvas20110108").getContext('2d'), 200, 50, 200, 0);
});
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2011/01/08/%e4%ba%8c%e5%88%86%e6%9c%a8%e3%81%a8%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScriptで二分探索木</title>
		<link>http://blog.justoneplanet.info/2010/12/25/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/</link>
		<comments>http://blog.justoneplanet.info/2010/12/25/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/#comments</comments>
		<pubDate>Fri, 24 Dec 2010 20:51:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[探索]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=3588</guid>
		<description><![CDATA[二分探索木とは二分木と同じ構造で、左の子＜親＜右の子となっているものですな。 ■二分探索木に対する挿入 以下のようにして、二分探索木（Binary Search Tree）に対する挿入を実装してみた。linked lis [...]]]></description>
			<content:encoded><![CDATA[<p>二分探索木とは二分木と同じ構造で、左の子＜親＜右の子となっているものですな。</p>
<h3>■二分探索木に対する挿入</h3>
<p>以下のようにして、二分探索木（Binary Search Tree）に対する挿入を実装してみた。linked listで再現したほうがイメージしやすい気もするがコード量は増えるので配列を使用した。</p>
<pre class="brush: jscript;">
Array.prototype.bpush = function(elm){
    var ary  = this;
    var push = function(elm, key){
        if(!ary[key]){
            ary[key] = elm;
        }
        else{
            if(elm &lt; ary[key]){// left child
                push(elm, 2 * key + 1);
            }
            else{// right child
                push(elm, 2 * key + 2);
            }
        }
    }
    push(elm, 0);
}

var bst = [];
bst.bpush(5);
bst.bpush(7);
bst.bpush(8);
bst.bpush(3);
console.log(bst);// [5, 3, 7, undefined, undefined, undefined, 8]// ex1

var bst = [];
bst.bpush(7);
bst.bpush(2);
bst.bpush(5);
bst.bpush(1);
console.log(bst);// [7, 2, undefined, 1, 5]// ex2

var bst = [];
bst.bpush(1);
bst.bpush(2);
bst.bpush(3);
bst.bpush(4);
console.log(bst);// [1, undefined, 2, undefined, undefined, undefined, 3, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 4]// ex3
</pre>
<p>ソート済みの配列を格納した場合、上述ex3に見られるように線形リストとなり下述の探索性能が下がる。</p>
<h3>■探索</h3>
<p>上述で生成した二分探索木を探索するアルゴリズムを実装した。</p>
<pre class="brush: jscript;">
Array.prototype.bpush = function(elm){
    var ary  = this;
    var push = function(elm, key){
        if(!ary[key]){
            ary[key] = elm;
        }
        else{
            if(elm &lt; ary[key]){// left child
                push(elm, 2 * key + 1);
            }
            else{// right child
                push(elm, 2 * key + 2);
            }
        }
    }
    push(elm, 0);
}

Array.prototype.bsearch = function(elm){
    var ary    = this;
    var search = function(elm, key){
        if(!ary[key]){
            return -1;
        }
        if(elm === ary[key]){
            return key;
        }
        else{
            if(elm &lt; ary[key]){
                return search(elm, 2 * key + 1);
            }
            else{
                return search(elm, 2 * key + 2);
            }
        }
    }
    return search(elm, 0);
}

var bst = [];
bst.bpush(5);
bst.bpush(7);
bst.bpush(8);
bst.bpush(3);
console.log(bst);// [5, 3, 7, undefined, undefined, undefined, 8]
console.log(bst.bsearch(3));// 1

var bst = [];
bst.bpush(7);
bst.bpush(2);
bst.bpush(5);
bst.bpush(1);
console.log(bst);// [7, 2, undefined, 1, 5]
console.log(bst.bsearch(3));// -1

var bst = [];
bst.bpush(1);
bst.bpush(2);
bst.bpush(3);
bst.bpush(4);
console.log(bst);// [1, undefined, 2, undefined, undefined, undefined, 3, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 4]
console.log(bst.bsearch(3));// 6
</pre>
<p>まぁこんな感じ。前述の通りex3は線形リストのシーケンシャル探索と同じとなり性能が低下する。従って、要素の挿入と削除に対して、ツリーの平衡を維持するようなロジックを導入する必要がある。代表的なものとして<a href="http://ja.wikipedia.org/wiki/%E8%B5%A4%E9%BB%92%E6%9C%A8">赤黒木</a>などがある。</p>
<h3>■特性</h3>
<ul>
<li>最悪時の計算コストはO(n)。平均時はO(log n)となる</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/12/25/javascript%e3%81%a7%e4%ba%8c%e5%88%86%e6%8e%a2%e7%b4%a2%e6%9c%a8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

