@blog.justoneplanet.info

日々勉強

JavaScriptで二分探索木

二分探索木とは二分木と同じ構造で、左の子<親<右の子となっているものですな。

■二分探索木に対する挿入

以下のようにして、二分探索木(Binary Search Tree)に対する挿入を実装してみた。linked listで再現したほうがイメージしやすい気もするがコード量は増えるので配列を使用した。

Array.prototype.bpush = function(elm){
    var ary  = this;
    var push = function(elm, key){
        if(!ary[key]){
            ary[key] = elm;
        }
        else{
            if(elm < 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

ソート済みの配列を格納した場合、上述ex3に見られるように線形リストとなり下述の探索性能が下がる。

■探索

上述で生成した二分探索木を探索するアルゴリズムを実装した。

Array.prototype.bpush = function(elm){
    var ary  = this;
    var push = function(elm, key){
        if(!ary[key]){
            ary[key] = elm;
        }
        else{
            if(elm < 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 < 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

まぁこんな感じ。前述の通りex3は線形リストのシーケンシャル探索と同じとなり性能が低下する。従って、要素の挿入と削除に対して、ツリーの平衡を維持するようなロジックを導入する必要がある。代表的なものとして赤黒木などがある。

■特性

  • 最悪時の計算コストはO(n)。平均時はO(log n)となる

コメントはまだありません»

No comments yet.

RSS feed for comments on this post.TrackBack URL

Leave a comment