# 深度实战玩转算法 -- 选择排序算法可视化

2017.09.12 20:19 7440浏览

### index.html

``````<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<title>选择排序算法动画</title>
<body style="height: 100%, width: 1000px;">
<canvas id="canvas" style="height: 100%">
当前浏览器不支持Canvas，请更换浏览器后再试
</canvas>

<script type="text/javascript">
var sceneWidth = 1000;
var sceneHeight = 600;

var canvas = document.getElementById('canvas');
var g2d = canvas.getContext('2d');

canvas.width = sceneWidth;
canvas.height = sceneHeight;

var N = 100;

var visualizer = new AlgoVisualizer(g2d, sceneWidth, sceneHeight, 100);
}
</script>
</body>
</html>``````

### AlgoVisHelper.js

``````class AlgoVisHelper{
// 构造函数
constructor() {}

static fillRectangle(g2d, x, y, w, h){
g2d.fillRect(x, y, w, h);
}

static setColor(g2d, color){
g2d.fillStyle = color;
}
}

// 类中的静态属性
AlgoVisHelper.Red = "#F44336";
AlgoVisHelper.Pink = "#E91E63";
AlgoVisHelper.Purple = "#9C27B0";
AlgoVisHelper.DeepPurple = "#673AB7";
AlgoVisHelper.Indigo = "#3F51B5";
AlgoVisHelper.Blue = "#2196F3";
AlgoVisHelper.LightBlue = "#03A9F4";
AlgoVisHelper.Cyan = "#00BCD4";
AlgoVisHelper.Teal = "#009688";
AlgoVisHelper.Green = "#4CAF50";
AlgoVisHelper.LightGreen = "#8BC34A";
AlgoVisHelper.Lime = "#CDDC39";
AlgoVisHelper.Yellow = "#FFEB3B";
AlgoVisHelper.Amber = "#FFC107";
AlgoVisHelper.Orange = "#FF9800";
AlgoVisHelper.DeepOrange = "#FF5722";
AlgoVisHelper.Brown = "#795548";
AlgoVisHelper.Grey = "#9E9E9E";
AlgoVisHelper.BlueGrey = "#607D8B";
AlgoVisHelper.Black = "#000000";
AlgoVisHelper.White = "#FFFFFF";
``````

### AlgoFrame.js

``````class AlgoFrame{

constructor(g2d, title, canvasWidth, canvasHeight) {
this.g2d = g2d;
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
}

getCanvasWidth() {
return this.canvasWidth;
}

getCanvasHeight() {
return this.canvasHeight;
}

repaint(){
// 具体绘制
this.g2d.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

var w = this.canvasWidth / this.data.N();

for (var i = 0; i < this.data.N(); i++) {
if(i < this.data.orderedIndex){
AlgoVisHelper.setColor(this.g2d, AlgoVisHelper.Red);
}else{
AlgoVisHelper.setColor(this.g2d, AlgoVisHelper.Grey);
}
if(i == this.data.currentCompareIndex){
AlgoVisHelper.setColor(this.g2d, AlgoVisHelper.LightBlue);
}
if(i == this.data.currentMinIndex){
AlgoVisHelper.setColor(this.g2d, AlgoVisHelper.Indigo);
}
AlgoVisHelper.fillRectangle(this.g2d, i * w, this.canvasHeight - this.data.get(i), w - 1, this.data.get(i));
}
}

render(data) {
this.data = data;
this.repaint();
}
}``````

### SelectionSortData.js

``````class SelectionSortData{

constructor(N, randomBound){

this.numbers = new Array(N);
this.orderedIndex = -1;         // [0...orderedIndex) 是有序的
this.currentCompareIndex = -1;  // 当前正在比较的元素索引
this.currentMinIndex = -1;      // 当前找到的最小元素的索引

for( var i = 0 ; i < N ; i ++){
this.numbers[i] = parseInt((Math.random()*randomBound)) + 1;
}
}

N(){
return this.numbers.length;
}

get(index){
if( index < 0 || index >= this.numbers.length){
throw ReferenceError("Invalid index to access Sort Data.");
}

return this.numbers[index];
}

swap(i, j) {

if( i < 0 || i >= this.numbers.length || j < 0 || j >= this.numbers.length){
throw ReferenceError("Invalid index to access Sort Data.");
}

var t = this.numbers[i];
this.numbers[i] = this.numbers[j];
this.numbers[j] = t;
}

}``````

### AlgoVisualizer.js

``````class AlgoVisualizer {
constructor(g2d, sceneWidth, sceneHeight, N) {

// 动画的执行速度[毫秒]
this.DELAY = 5;

this.g2d = g2d;

// 初始化数据
this.data = new SelectionSortData(N, sceneHeight);

// 动画整个存储
this.data_list = new Array();

// 初始化视图
this.frame = new AlgoFrame(g2d, "Selection Sort Visualization", sceneWidth, sceneHeight);
this.run();
}

// 生成数据逻辑
run() {
this.setData(0, -1, -1);

for (var i = 0; i < this.data.N(); i++) {
// 寻找[i, n) 区间里的最小值的索引
// [0,1) 前闭后开 0 <= n < 1
var minIndex = i;
this.setData(i, -1, minIndex);
for (var j = i + 1; j < this.data.N(); j++) {
this.setData(i, j, minIndex);
if (this.data.get(j) < this.data.get(minIndex)) {
minIndex = j;
this.setData(i, j, minIndex);
}
}
this.data.swap(i, minIndex);
this.setData(i + 1, -1, -1);
}
this.setData(this.data.N(), -1, -1);
// 渲染数据
this.render();
}

setData(orderedIndex, currentCompareIndex, currentMinIndex) {
var data = new SelectionSortData();
data.orderedIndex = orderedIndex;
data.currentCompareIndex = currentCompareIndex;
data.currentMinIndex = currentMinIndex;
data.numbers = this.data.numbers.slice();
this.data_list[this.data_list.length] = data
}

render(){
var i = 0;
setInterval(() => {
if(i < this.data_list.length){
this.frame.render(this.data_list[i]);
i++;
}
}, this.DELAY);
}
}``````

32人点赞

• 32
• 2
• 收藏
• 共同学习，写下你的评论

0/150