LoginSignup
2
3

More than 5 years have passed since last update.

Webブラウザ上でバブルソートの可視化

Last updated at Posted at 2017-10-30

少々冗長なコードになってしまったがバブルソートを可視化できたのでメモ

グラフ(html)を何度も再描画しているのでシンプルに処理が遅い(笑)
Ajaxを使ったら早くなる・・・のだろうか?
Ajaxは今後触れる予定
setIntervalを使わないと関数を実行してから終了形まで一気にグラフが描画されてしまうのでグラフが並び変わっていく様を楽しめなかった。
これは一つの関数が実行し終えるまでhtmlは再描画できないという仕様なのだそう。(当然のことではあるが・・・)
よってsetIntervalで一回一回並び替えをするごとに関数を終了させ、それを短いスパンで繰り返している。
音源は適当な機械音を鳴らしている。

バブルソート↓clickすると動画が再生されます
バブルソート

html
genGraph()関数でdiv要素内ににグラフを生成する
dummyクラスは値をheightとwidthに保持するダミー要素

index.html
<!DOCTYPE htlm>
<head>
    <meta charset="utf-8">
    <title>sort</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <link rel="stylesheet" type="text/css" href="css/bootstrap-4.0.0-beta.2-dist/css/bootstrap.min.css">
    <audio src="sound.mp3" loop autoplay="auto"></audio>
</head>
<body>
    <div id="wrap" onClick="genGraph()"></div>
    <div onClick="funcStart()">change</div>
    <div class="dummy"></div>
    <div class="iValue">i = 0</div>
    <div class="jValue">j = 0</div>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="js/javascript.js"></script>
</body>
</html>

jQuery
numはグラフの数を表し、自由に設定可能、以下関数説明

genGraph()・・・グラフをnumの数だけ生成し、それぞれのグラフに異なるidを付与
generate_randomx(count)・・・重複しない乱数をnumの数だけ生成し、グラフのheightに割り当て
changeGraph(x, y)・・・idがxとyの要素の高さを入れ替える
getArray()・・・実行時のグラフの各々のheightを配列に格納しその配列を返す
bbsor(arr, i, j)・・・バブルソートのアルゴリズムを実行し、その結果をdummyクラスのheightとwidthに格納
prepare()・・・アルゴリズム実行の前準備
funcStart()・・・setIntervalを用いてhtmlを再描画している
timerOff()・・・setIntervalをストップしdummyクラスを初期化
prepare2(flag)・・・処理が完了し、グラフを緑に塗り替えるための前準備
changeColor(i)・・・グラフの背景色を左から右へgreenに変える

javascript.js
var num = 100;

function genGraph() {
    var str = "<div class='graph' id=no" + 0 +"></div>";
    for (var i = 1; i < num; i++) {
        str += "<div class='graph' id=no" + i +"></div>";   
    }

    $("#wrap").html(str);
    var arr = new Array();
    arr = generate_randomx(num);

    for (var i = 0; i < num; i++) {
        rand = arr[i];
        rand = rand * 4 + 'px';
        var no = "#no" + i;
        $(no).css('height', rand);
    }
}
function generate_randomx(count) {
  //生成した乱数を格納する配列を初期化
  var generated = new Array();
  //生成した乱数を格納している配列の長さ(生成した乱数の数)
  var generatedCount = generated.length;
  //パラメータ count の数だけ Math.random()で乱数を発生
  for(var i = 0 ; i < count; i++){
    var candidate = Math.floor(Math.random() * count);
    //今まで生成された乱数と同じ場合は再度乱数を発生
    for(var j = 0; j < generatedCount; j++) {
      if(candidate == generated[j]){
        candidate = Math.floor(Math.random() * count);
        j= -1;
      }
    }
    generated[i] = candidate;  
    generatedCount++;
  }
  return generated;  
}

function changeGraph(x, y) {
    var xHeight = $(x).outerHeight();
    var yHeight = $(y).outerHeight();
    var temp = xHeight;
    xHeight = yHeight;
    yHeight = temp;
    $(x).css('height', xHeight + 'px');
    $(y).css('height', yHeight + 'px');
    for (var i = 0; i < num; i++) {
        $('#no' + i).css('background-color', '#fff');
    }
    $(x).css('background-color', 'red');

}

function getArray() {
    var arr = new Array(0);
    for (var i = 0; i < num; i++) {
        var noHeight = $("#no" + i).outerHeight();
        arr.push(noHeight);
    }
    return arr;
}

function bbsor(arr, i, j) {
    console.log("i:" + i);
    console.log("j:" + j);

    j -= 1;
    if (j == i) {
        i +=1
        j = num - 1;
    }

    if (arr[j] < arr[j - 1]) {
        temp = arr[j];
        arr[j] = arr[j - 1];
        arr[j - 1] = temp;
        var x = '#no' + j;
        var dummy = j - 1;
        var y = '#no' + dummy;
        changeGraph(x, y);
    }
    if (i == 0 && j == 0) {
        i += 1;
    }
    $(".dummy").html(arr);
    $(".dummy").css('height', i + 'px');
    $(".dummy").css('width', j + 'px');

    console.log(arr);
}

function prepare() {
    arr = getArray();
    var i = $('.dummy').outerHeight();
    var j = $('.dummy').outerWidth();
    if (i == 0 && j == 0) {
        var j = num;
    } else {
        var j = $('.dummy').outerWidth();
    }
    if (i == num - 1 && j == 0) {
        timerOff(); 
    }
    bbsor(arr, i , j);
    $(".iValue").html('i = ' + i);
    $(".jValue").html('j = ' + j);
}

function funcStart() {
    timer = setInterval('prepare()', 1);
}

function timerOff() {
    clearInterval(timer);
    $('.dummy').css('height', '0px');
    timer2 = setInterval('prepare2()', 10); 
}

function prepare2(flag) {
    a = $('.dummy').outerHeight();
    console.log(a);
    if (flag == 0) {
        i = 0;
    } else {
        var i = $('.dummy').innerHeight();
    }
    changeColor(i);
}

function changeColor(i) {
    k = i - num + 1;
    $('#no' + k).css('background-color', 'green');
    i += 1;
    $('.dummy').css('height', i + 'px');
    if (k == num - 1) {
        clearInterval(timer2);  
    }
}
style.css
#wrap {
    width: 100%;
    height: 500px;
    background-color: #191919;
    display: flex;
    align-items: flex-end;
}

.graph {
    /*border: 1px solid #ccc;*/
    height: 5px;
    width: 10px;
    background-color: #fff;
}

.dummy {
    display: none;
    height: 0;
    width: 0;
}

.iValue {
    position: absolute;
    top: 20px;
    left: 20px;
    color: #fff;
}

.jValue {
    position: absolute;
    top: 40px;
    left: 20px;
    color: #fff;
}

クイックソートも作りたい。

ちなみにyoutubeでsortって調べるともっとすごい人がつくってるやつでてくるのでオススメ(今回はそれを参考に作った)

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3