質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

WebGL

WebGL(ウェブジーエル)は、ウェブブラウザで 3次元コンピュータグラフィックスを表示させるための標準仕様です。

Q&A

0回答

1042閲覧

Javascript Three.js でクイックソートの工程を可視化するためのプログラムに関しての質問

Rinoa

総合スコア0

Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

WebGL

WebGL(ウェブジーエル)は、ウェブブラウザで 3次元コンピュータグラフィックスを表示させるための標準仕様です。

0グッド

1クリップ

投稿2021/12/12 10:08

前提・実現したいこと

実現したいこと:クイックソートが完全に完了するまでの過程を、一回のキーボード入力で並び替えを一工程ずつ可視化できるようにしたい。
※一回のキーボード入力でクイックソートを一括で完全に完了するプログラムは既にできています。

現在Javascriptを用いてクイックソートの可視化を行えるプログラムを作っています。
現状できているプログラムは以下の用途で動くようなものになっています。
1). キーボードの1~5を入力すると、それに応じたモデルがページ上に表示されて横一列に並ぶ。数字が小さいモデルほどそれに該当するモデルの大きさも小さい。
2). 例えばキーボードで3421523135と入力されたら、各々のモデルがその順番で横一列に並ぶ。そしてこれをいわゆるクイックソートを実行する前の未整列の配列とする。
3). エンターキーを入力するとこの配列に一括でクイックソートが実行され、2).の配列は瞬時に1122333455という順で整列する。同じくページ上に表示されているモデルたちも昇順で表示されるようになる。
ここまでは完成済

ここで上述の通り、この3).における並び替えを一括ではなく一工程ずつ可視化できるようにしたいです。
4). キーボードのA(キーコード65)を入力する度に、一工程ずつ並び替えを可視化する。
5). すべての工程が終了、つまり3).と同じ状態になった時、並び替えを終了(trace end)と宣言する。

以下のプログラムに何が足りないのか、何を修正するべきかなど、有識者の方なにかご教授いただければ幸いです。

発生している問題・エラーメッセージ

4). の並び替えが頻繁におかしな挙動を取る。
5). 4).で仮に上手く並び替えができたとしても終了(trace end)と宣言されない時がある。そもそも変な並び順でtrace endと宣言されることが多い。
下記の動画を見ていただければ分かりやすいかと...
https://youtu.be/aezBM7t3OzE

コード

// 起動されたときに呼ばれる関数を登録する window.addEventListener('load', () => { //まずステージを整える initialize(); }); function initialize() { // レンダラーを作成 const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('#canvas'), antialias: true }); // シーンを作成 const scene = new THREE.Scene(); /* var clock = new THREE.Clock();*/ // カメラを作成 const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(7, 0, 10); //camera.lookAt(new THREE.Vector3(0, 0, 0)); // Load GLTF or GLB var loader = new THREE.GLTFLoader(); var count = 0; url1 = 'img/1.gltf'; url2 = 'img/2.gltf'; url3 = 'img/3.gltf'; url4 = 'img/4.gltf'; url5 = 'img/5.gltf'; let urlList = [ url1,url2,url3,url4,url5, ]; //テクスチャをガンマ補正 renderer.gammaOutput = true; renderer.gammaFactor = 2.2; // ライト追加 hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x4169e1, 1.8); scene.add(hemisphereLight); var directionalLight = new THREE.DirectionalLight(0xFFFFFF, 1.0); // 光源色と光強度を指定して生成 directionalLight.position.set(20, 20, 100); // 光源位置を設定 scene.add(directionalLight); // シーンに追加 // フィールドサイズ追加 // 高さが全部入るように調整 // 初回実行 loop(); onResize(); // リサイズイベント発生で実行 window.addEventListener('resize', onResize); function onResize() { // サイズを取得 const w = window.innerWidth; const h = window.innerHeight; // 描画サイズ renderer.setSize(w, h); // ピクセル比 renderer.setPixelRatio(window.devicePixelRatio); // 空間の背景色 //0xから始まる16進数の色コード renderer.setClearColor(new THREE.Color(0xEEEEEE)); // カメラのアスペクト比を正す camera.aspect = w / h; camera.updateProjectionMatrix(); // レンダリング renderer.render(scene, camera); } let i = 0; let model = []; model[i] = null; let qsortCnt = 0; let qsortQueue = []; let mb = []; var s1 = 0.1; var s2 = 0.2; var s3 = 0.3; var s4 = 0.4; var s5 = 0.5; let sSize = [ s1,s2,s3,s4,s5, ]; function loop() { requestAnimationFrame(loop); document.body.onkeydown = (e) => { // キーボードが押された場合 switch (e.keyCode) { case 49: //1キー modeladd(0); qsortCnt = 0; return false; case 50: //2キー modeladd(1); qsortCnt = 0; return false; case 51: // 3キー modeladd(2); qsortCnt = 0; return false; case 52: // 4キー modeladd(3); qsortCnt = 0; return false; case 53: // 5キー modeladd(4); qsortCnt = 0; return false; case 13: //Enterキー (一括クイックソート) quickSort(0,mb.length-1); for (var si = 0; si < i + 1; si++) { model[si].position.set(si, 0, -10); } return false; case 65: //Aキー (1つ1つクイックソート) if(qsortCnt == 0){ while(qsortQueue.length){ qsortQueue.shift(); } console.log(qsortQueue); quickSortV2(0,mb.length-1); qsortCnt = 1; console.log("qsortQueue"); console.log(qsortQueue); console.log("end"); } if(qsortQueue.length){ let tmpData = qsortQueue.shift(); // オブジェクトの削除 for(var sj = 0;sj < model.length;sj++){ scene.remove(model[sj]); } while(model.length)model.shift(); // オブジェクトの新規作成 i=0; for(var sj = 0;sj < tmpData.length; sj++){ modeladd(tmpData[sj]); } } else{ console.log("trace end"); qsortCnt = 0; } return false; } }; renderer.render(scene, camera); if (count == 1) { /*if(i==XX){ //指定のモデル個数を超えた際追加不可 }*/ } } function modeladd(x){ loader.load( urlList[x], function (gltf) { model[i] = gltf.scene; model[i].scale.set(sSize[x], sSize[x], sSize[x]); model[i].position.set(i, 0, -10); scene.add(model[i]); count = 1; mb[i] = x; i += 1; }, ); } //クイックソート関数 function quickSort(startID,endID){ //範囲の間にある値をピポットに設定する var pivot = mb[Math.floor((startID + endID)/2)]; //引数を左端、右端として変数にいれる var left = startID; var right = endID; //ピポットより小さい値を左側へ、大きい値を右側へ分割する while(true){ //leftの値がpivotより小さければleftを一つ右へ移動する while(mb[left]<pivot){ left++; } //rightの値がpivotより小さければrightを一つ左へ移動する while(pivot<mb[right]){ right--; } //leftとrightの値がぶつかったら、そこでグループ分けの処理を止める。 if(right <= left){ break; } //rightとrightの値がぶつかっていない場合、leftとrightを交換 //交換後にleftを後ろへ、rightを前へ一つ移動する var tmp =mb[left]; mb[left] =mb[right]; mb[right] =tmp; var tmp2 = model[left]; model[left] = model[right]; model[right] = tmp2; left++; right--; console.log(mb); } //左側に分割できるデータがある場合、quickSort関数を呼び出して再帰的に処理を繰り返す。 if(startID < left-1){ quickSort(startID,left-1); } //右側に分割できるデータがある場合、quickSort関数を呼び出して再帰的に処理を繰り返す。 if(right+1 < endID){ quickSort(right+1,endID); } } //クイックソート関数 function quickSortV2(startID,endID){ //範囲の間にある値をピポットに設定する var pivot = mb[Math.floor((startID + endID)/2)]; //引数を左端、右端として変数にいれる var left = startID; var right = endID; //ピポットより小さい値を左側へ、大きい値を右側へ分割する while(true){ //leftの値がpivotより小さければleftを一つ右へ移動する while(mb[left]<pivot){ left++; } //rightの値がpivotより小さければrightを一つ左へ移動する while(pivot<mb[right]){ right--; } //leftとrightの値がぶつかったら、そこでグループ分けの処理を止める。 if(right <= left){ break; } //rightとrightの値がぶつかっていない場合、leftとrightを交換 //交換後にleftを後ろへ、rightを前へ一つ移動する var tmp =mb[left]; mb[left] =mb[right]; mb[right] =tmp; var tmp2 = model[left]; model[left] = model[right]; model[right] = tmp2; left++; right--; qsortQueue.push(mb); } //左側に分割できるデータがある場合、quickSort関数を呼び出して再帰的に処理を繰り返す。 if(startID < left-1){ quickSortV2(startID,left-1); } //右側に分割できるデータがある場合、quickSort関数を呼び出して再帰的に処理を繰り返す。 if(right+1 < endID){ quickSortV2(right+1,endID); } } }

参考文献

https://qiita.com/may88seiji/items/a08504d472b5cec5f916
https://algorithm-visualizer.org/divide-and-conquer/quicksort

補足情報

使用環境:VSCode
ブラウザ:Googlechrome

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問