看到网上有老外写的,就拿起自已之前完成的jmgraph画图组件也写了一个。
想了解jmgraph的请移步:https://github.com/jiamao/jmgraph

当前演示请查看:http://graph.jm47.com/example/sort.html

<!doctype html>
<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type" /><title>排序算法演示</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="http://mat1.gtimg.com/www/mobi/js/zepto.min.js"></script><!--[if lt IE 9]><script type="text/javascript" src="../../jmgraph/src/lib/excanvas.js"></script><![endif]-->    <!--<script type="text/javascript" src="../src/jmgraph.debug.js"></script>    --><script type="text/javascript" src="../dist/jmGraph.min.js"></script></head><button id="btn_quick" href="#">快速排序</button><button id="btn_straightinsertion" href="#">直接插入排序</button><button id="btn_shell" href="#">希尔排序</button><button id="btn_simpleselection" href="#">简单选择排序</button><button id="btn_simpleselection2" href="#">二元选择排序</button><button id="btn_bubble" href="#">冒泡排序</button><body style="width:100%;"><div id="mycanvas" style="border:1px solid #ddd;width:100%;"></div>        </body><script type="text/javascript">//排序管理对象function jmSort() {//原始数组个数this.arrCount = 20;//原始数组this.source = [];var container = document.getElementById('mycanvas');this.canvasWidth = Math.min(600, document.getElementById('mycanvas').offsetWidth - 10);container.style.width = this.canvasWidth + 'px';this.canvasHeight = Math.min(450, window.innerHeight - 10);container.style.height = this.canvasHeight + 'px';this.graph = new jmGraph('mycanvas',this.canvasWidth,this.canvasHeight);                this.rectStyle = {stroke:'rgb(173,173,209)',lineWidth:1,close:true,fill: 'rgb(8,209,54)'};this.disableStyle = {stroke:'rgba(173,173,209,0.8)',lineWidth:1,close:true,fill: 'rgba(88,196,113,0.5)'};//this.rectStyle.shadow = this.graph.createShadow(2,2,2,'rgb(39,40,34)');this.selectRectStyle = {stroke:'rgb(120,20,80)',lineWidth:1,zIndex: 100,close:true,fill: 'rgba(255,180,5,0.7)'};//this.selectRectStyle.shadow = this.graph.createShadow(4,4,6,'rgb(39,40,34)');//基准样式this.datumRectStyle = {stroke:'rgb(224,84,68)',lineWidth:2,close:true,zIndex: 50,lineType: 'dotted',fill: 'rgba(224,84,68,0.7)'};this.labelStyle = {stroke:'rgb(120,20,80)',textAlign: 'center',textBaseline: 'middle',font: '12px Arial',lineWidth:1};}//延迟数组循环
            jmSort.prototype.arrayTimeout = function(arr, fun, endfun, t, index, end) {index = index || 0;end = end || arr.length;var t = t || 200;var self = this;function intervalArr() {if(index >= end) {endfun && endfun(); return;}var r = fun(index, arr[index], function(){index ++;self.timeoutHandler = setTimeout(intervalArr, t);});if(r === false) {endfun && endfun(); return}}intervalArr();}//柱子移动动画
            jmSort.prototype.rectAnimate = function(rect, cb) {if(typeof index == 'function') {cb = index;index = 0;}if(!rect.length) {rect = [rect];}var tox = [];var offx = [];var pos = [];var count = rect.length;for(var i=0;i<count;i++) {pos[i] = rect[i].rect.position();//重新计算其x坐标
                    tox[i] = this.xStep * rect[i].index + 10;offx[i] = (tox[i] - pos[i].x) / 20;}var self = this;function move() {var complete = 0;for(var i=0;i<count;i++) {pos[i].x += offx[i];if(offx[i] ==0 || (offx[i] > 0 && pos[i].x >= tox[i]) || (offx[i] < 0 && pos[i].x <= tox[i])) {pos[i].x = tox[i];    complete++;                    }                    }self.graph.redraw();if(complete >= count) {cb && cb();}else {self.aniTimeoutHandler = setTimeout(move, 20);}                    }move();                }//播放动画
            jmSort.prototype.play = function(frames, callback) {if(typeof frames == 'function') {callback = frames;frames = null;}frames = frames || this.frames;if(frames.length == 0) {callback && callback();return;}var f = frames.splice(0,1)[0];//取最早的一个var self = this;if(f.move && f.move.length) {//var count = 0;//for(var i=0;i<f.move.length;i++) {this.rectAnimate(f.move, function(){//count ++;//if(count >= f.move.length) {                                self.play(callback);//}
                        });//}
                }else if(f.sels) {this.selectRect.apply(this, f.sels);this.play(callback);//setTimeout(function(){//    self.play(callback);//}, 40);
                }else if(f.datum) {if(this.datumLine) {var start = this.datumLine.start();var end = this.datumLine.end();start.y = end.y = f.datum.rect.position().y;this.datumLine.visible = true;}this.play(callback);}else if(f.refresh) {this.refreshGraph(f.refresh);this.play(callback);}    else {this.play(callback);}            }//初始化排序条件,原始数组
            jmSort.prototype.init = function(){this.source = [];this.frames = [];var max = 100;var offy = this.canvasHeight - 20;this.graph.children.clear();//当前 x轴分布单位宽度this.xStep = (this.canvasWidth - 20) / this.arrCount;for(var i=0;i<this.arrCount;i++) {var v = {};v.value = Math.floor(Math.random() * max);v.height = v.value / max * offy;this.source.push(v);}//画基准线this.datumLine = this.graph.createLine({x:0,y:0},{x:this.canvasWidth,y:0},this.datumRectStyle);this.datumLine.visible = false;this.graph.children.add(this.datumLine);this.refreshGraph(this.source);}jmSort.prototype.reset = function() {if(this.timeoutHandler) clearTimeout(this.timeoutHandler);if(this.aniTimeoutHandler)     clearTimeout(this.aniTimeoutHandler);if(this.datumLine) this.datumLine.visible = false;//this.refreshGraph();    this.init();        }//刷新画布
            jmSort.prototype.refreshGraph = function(arr) {arr = arr || this.source;//this.graph.children.clear();var offy = this.canvasHeight - 20;for(var i=0;i<arr.length;i++) {    if(arr[i].rect) {var pos = arr[i].rect.position();pos.x = this.xStep * i + 10;}else {    var pos = {};pos.x = this.xStep * i + 10;pos.y = offy - arr[i].height;arr[i].rect = this.graph.createShape('rect',{position:pos,width: 10, height: arr[i].height, style: this.rectStyle});var label = this.graph.createShape('label',{style:this.labelStyle,position:{x:0,y:arr[i].height},value:arr[i].value,width:10,height:20});arr[i].rect.children.add(label);this.graph.children.add(arr[i].rect);}//this.graph.children.add(arr[i].rect);
                }this.graph.redraw();}//选中某几个值,则加亮显示
            jmSort.prototype.selectRect = function(datum, sels, area) {var self = this;this.graph.children.each(function(i, rect) {if(!rect.is('jmRect')) return;if(sels && sels.indexOf(rect) > -1) {rect.style = self.selectRectStyle;}else if(datum && datum.indexOf(rect) > -1) {rect.style = self.datumRectStyle;}else if(area && area.indexOf(rect) > -1) {rect.style = self.rectStyle;}                    else {rect.style = self.disableStyle;}});this.graph.refresh();}//快速排序//取其中一个值,把小于此值的放到其左边,大于此值的放到其右边//如此递归
            jmSort.prototype.quickSort = function(arr, callback) {if(typeof arr == 'function') {callback = arr;arr = null;}arr = arr || this.source;var self = this;function sort(source, oldleft, oldrigth) {if(source.length <= 1) return source;//取一个值做为比较对象,这里直接取中间的值(任务一个都可)var mindex = Math.floor(source.length /2);                var m = source[mindex];//基准值
                    self.frames.push({datum: m});//选中当前区域var area = [];for(var i=0;i<source.length;i++) {area.push(source[i].rect);}self.frames.push({sels:[[m.rect],null, area]});var left = mindex>0?source.slice(0, mindex):[];var right = mindex>0&&mindex<source.length-1?source.slice(mindex+1):[];var middle = [m];var index = oldleft?oldleft.length:0;for(var i=0;i<source.length;i++) {var s = source[i];self.frames.push({sels:[[m.rect],[s.rect], area]});var f = {move:[]};var sindex = i;if(s.value < m.value) {if(i < mindex) continue;left.push(s);var rindex = right.indexOf(s);right.splice(rindex, 1);sindex = left.length - 1;f.move.push({rect: s.rect,index: sindex + index});var movearr = middle.concat(right);for(var j=0;j<rindex+middle.length;j++) {f.move.push({rect: movearr[j].rect,index: sindex + index + j + 1});}}else if(s.value > m.value) {if(i > mindex) continue;var lindex = left.indexOf(s);                            left.splice(lindex, 1);right.unshift(s);sindex = left.length + middle.length;f.move.push({rect: s.rect,index: sindex + index});var movearr = left.concat(middle);for(var j=lindex;j<movearr.length;j++) {                                f.move.push({rect: movearr[j].rect,index: index + j});}}else if(i != mindex) {if(i < mindex) {var lindex = left.indexOf(s);left.splice(lindex, 1);middle.unshift(s);sindex = left.length;f.move.push({rect: s.rect,index: sindex + index});for(var j=lindex;j<left.length;j++) {f.move.push({rect: left[j].rect,index: index + j});}}if(i > mindex) {var rindex = right.indexOf(s);right.splice(right.indexOf(s), 1);middle.push(s);sindex = left.length + middle.length - 1;f.move.push({rect: s.rect,index: sindex + index});for(var j=0;j<rindex;j++) {f.move.push({rect: right[j].rect,index: sindex + index + j + 1});}}                            }if(f.move.length) self.frames.push(f);}return sort(left, oldleft, middle.concat(right, oldrigth||[])).concat(middle, sort(right, (oldleft||[]).concat(left, middle)));}                var result = sort(arr);                this.play(function(){callback && callback(result);});return result;}//直接插入排序//将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
            jmSort.prototype.straightInsertionSort = function(arr, dk, callback) {if(typeof arr == 'function') {callback = arr;arr= null;}if(typeof dk == 'function') {callback = dk;dk= 0;}arr = arr || this.source;dk = dk || 1;//拷贝一份var result = arr.slice(0);var self = this;for(var i=dk;i<result.length;i++) {var k = i;var j = k - dk;while(j>=0) {var v = result[k];var pre = result[j];this.frames.push({sels: [[v.rect], [pre.rect]]});if(v.value < pre.value) {result[j] = v;result[k] = pre;v.index = j;pre.index = k;this.frames.push({move: [{rect: pre.rect,index:k}, {rect:v.rect,index:j}]});k = j;j -= dk;}else {break;}}                    }callback && callback(result);return result;                }//希尔排序//先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
            jmSort.prototype.shellSort = function(arr, callback) {if(typeof arr == 'function') {callback = arr;arr = null;}arr = arr || this.source;var dk = Math.floor(arr.length / 2);var result = arr;while(dk >= 1) {result = this.straightInsertionSort(result, dk);dk = Math.floor(dk / 2);}this.play(function(){callback && callback(result);});return result;}//简单选择排序//在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
            jmSort.prototype.simpleSelectionSort = function(arr, callback) {if(typeof arr == 'function') {callback = arr;arr = null;}arr = arr || this.source.slice(0);for(var i=0;i<arr.length-1;i++) {var min = arr[i];var minindex = i;for(var j=i+1;j<arr.length;j++) {if(min.value > arr[j].value) {min = arr[j];minindex = j;}//this.frames.push({sels:[[min.rect], [arr[j].rect]]});
                    }if(minindex != i) {this.frames.push({sels:[[min.rect], [arr[i].rect]]});this.frames.push({move: [{rect: min.rect, index: i}, {rect: arr[i].rect, index: minindex}]});arr[minindex] = arr[i];arr[i] = min;}                    }this.play(function(){callback && callback(arr);});return arr;}//二元选择排序//简单选择排序,每趟循环只能确定一个元素排序后的定位。我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可
            jmSort.prototype.selection2Sort = function(arr, callback) {if(typeof arr == 'function') {callback = arr;arr = null;}arr = arr || this.source.slice(0);var index = -1;var self = this;var end = Math.floor(arr.length / 2);for(var i=0;i<end;i++) {//取最小值和最大值var min = arr[i];var max = arr[i];var minindex = i;var maxindex = i;for(var j=i+1;j<arr.length-i;j++) {if(min.value > arr[j].value) {min = arr[j];minindex = j;}if(max.value <= arr[j].value) {max = arr[j];maxindex = j;}}var maxpos = j - 1;this.frames.push({sels:[[min.rect, arr[i].rect], [max.rect, arr[maxpos].rect]]});if(minindex != i) {                        this.frames.push({move: [{rect: min.rect, index: i}, {rect: arr[i].rect, index: minindex}]});arr[minindex] = arr[i];arr[i] = min;//如果最大值是当前起始值,则它被换到最小值位置上了//需要重新改变最大值的索引为找到的最小值的索引if(maxindex == i) {maxindex = minindex;}}if(maxindex != maxpos) {                        this.frames.push({move: [{rect: max.rect, index: maxpos}, {rect: arr[maxpos].rect, index: maxindex}]});arr[maxindex] = arr[maxpos];arr[maxpos] = min;}        }this.play(function(){callback && callback(arr);});return arr;}//冒泡排序//在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
            jmSort.prototype.bubbleSort = function(arr, callback) {if(typeof arr == 'function') {callback = arr;arr = null;}arr = arr || this.source.slice(0);var i = arr.length - 1;while(i > 0) {var pos = 0;for(var j=0;j<i;j++) {this.frames.push({sels: [[arr[j].rect],[arr[j+1].rect]]});if(arr[j].value > arr[j+1].value) {pos = j;var tmp=arr[j];arr[j]=arr[j+1];arr[j+1]=tmp;this.frames.push({move: [{rect: tmp.rect,index: arr.indexOf(tmp)},{rect: arr[j].rect,index: arr.indexOf(arr[j])}]});}}i=pos;}this.play(function(){callback && callback(arr);});}$(function(){//开始var sort = new jmSort();sort.init();sort.selection2Sort(function(ret){console.log(ret);});        $('#btn_quick').click(function(){sort.reset();sort.quickSort(null,null,null,function(ret) {this.datumLine.visible = false;this.selectRect(ret);console.log(ret);});    return false;});$('#btn_straightinsertion').click(function(){sort.reset();sort.straightInsertionSort(function(result){sort.play();console.log(result);});return false;    });$('#btn_shell').click(function(){sort.reset();sort.shellSort();return false;    });$('#btn_simpleselection').click(function(){sort.reset();sort.simpleSelectionSort();    return false;});$('#btn_simpleselection2').click(function(){sort.reset();sort.selection2Sort();return false;                });$('#btn_bubble').click(function(){sort.reset();sort.bubbleSort();return false;});});</script>
</html>

转载于:https://www.cnblogs.com/jiamao/p/4679320.html

JS写的排序算法演示相关推荐

  1. 刚写完排序算法,就被开除了…

    刚写完这段代码,就被开除了-- 栈长前些天刚写完上面这篇文章,没几天,又来一个悲剧... 据说是一个月薪 9K 的 Java 程序员,因老板让他写一个排序算法,然后他就写了一段屌炸天的休眠排序算法,接 ...

  2. 34.写一个排序算法1-100随机数字进行排序

    编程题目: 34.写一个排序算法 1-100随机数字 进行排序,要求效率. 示例代码: package program.calculation.exercise34;/*** 34.写一个排序算法 1 ...

  3. Canvas制作排序算法演示动画

    tips: 形象化演示排序算法可以让初学者快速理解,比较好的例子:jun-lu的SortAnimate,旧金山大学的David Galles教授的算法演示课件.最近在看canvas,试着用js+can ...

  4. js实现常见排序算法

    文章目录 前言 一.排序相关概念 1.比较排序和非比较排序 比较排序 非比较排序 2.稳定性和不稳定性 二.各排序算法对比 三.排序算法中的通用函数以及对数器 1.通用函数 交换函数 取两索引的中间下 ...

  5. javascript写各种排序算法

    在知乎上看到这个题目,就自己写了一下,在这里附上链接,里面有各种排序的动态图,非常形象直观,有助于新手对排序算法理解,链接:常见排序算法之JavaScript实现 首先各种排序算法都会用到的交换函数: ...

  6. JS 常见的排序算法

    工作中算法不常用,但是排序经常用.因此在这里整理了几种JS中常见的排序算法. 冒泡排序 1.算法思想:判断两个相邻元素,大于则交换位置 2.算法步骤 从数组中第一个数开始,依次与下一个数比较并次交换比 ...

  7. js实现常用排序算法

    javascript实现常用排序算法 包括冒泡排序.插入排序.希尔排序.选择排序.快速排序等常用排序算法 1.冒泡排序 var bubbleSort = function (arr) {const n ...

  8. 写一个排序算法,可以是冒泡排序或者是快速排序,假设待排序对象是一个维数组。(提示:不能使用系统已有函数,另外请仔细回忆以前学习过的 基础知识)...

    //冒泡排序(数组排序) function bubble_sort($array) {$count = count($array);if ($count <= 0) return false;f ...

  9. 面试时写不出排序算法?看这篇就够了

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 作者:静默虚空 juejin.im/post/5cb6b8f551882532c334bcf2 ...

最新文章

  1. 查看linux虚拟机信息,虚拟机:Linux查看线程信息的步骤
  2. 为什么有些人从不点开朋友圈?
  3. RecordMyDesktop安装与使用
  4. c语言将一个实型变量f=55.5678,《C语言程序设计》第2章2 常量和变量
  5. 自学Java的人,如何系统全面的学习?
  6. Initializer Lists
  7. Hasura GraphQL 内部表结构
  8. 简易图解N合1集成安装光盘制作教程二
  9. 回顾RHCE——邮件收发实验
  10. 爬取 bilibili 弹幕数据
  11. input file 选择图片并显示
  12. Python爬取京东商品评论
  13. 中国银行 CA 密码无法输入(红叉)
  14. 中软国际java面试题及参考答案
  15. Git安装图文教程(Windows、Linux全平台)
  16. 抖音多账号批量上传视频软件
  17. 考研日语线上笔记(四):中级日语语法总结20课(1~10)
  18. 服务器和客户端是怎么信息交换的,服务器与客户端之间数据交互
  19. c#实现简单的手写板功能
  20. C语言模块化编程样例

热门文章

  1. Kinect深度图像滤波
  2. HLS协议及java切片相关
  3. 【转】为什么有天线的路由器信号还不如没有天线的路由
  4. 康力优蓝发布新品:让AI教育从概念变成现实!
  5. oracle vm 实施图解
  6. 16-01-25---Servlet复习笔记(01)
  7. 【转】Monkey测试6-Monkey Test Log
  8. XenApp_XenDesktop_7.6实战篇之九:SQL Server数据库服务器规划及部署
  9. android插件化-apkplug框架基本结构-01
  10. 比较windows phone程序启动和android程序启动原理