最近在搞一个好玩的东西,算法、前端学习两不误,哈哈,不废话,让大家看看效果
虽然有点不好看,css还需要优化一下,但是功能都齐全了,下面来看看代码
index部分:
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>排序算法动画演示</title>
<link rel="stylesheet" href="css/style.css" />
<script type="text/javascript" src="js/SortAnimate.js"></script>
<script type="text/javascript" src="js/cocktail.js"></script>
<script type="text/javascript" src="js/bubble.js"></script>
<script type="text/javascript" src="js/comb.js"></script>
<script type="text/javascript" src="js/insert.js"></script>
<script type="text/javascript" src="js/oddEven.js"></script>
<script type="text/javascript" src="js/quick.js"></script>
<script type="text/javascript" src="js/selection.js"></script>
<script type="text/javascript" src="js/shell.js"></script>
</head>
<body>
<div style="margin:50px;">
<h1>排序算法动画演示</h1>
<div>
<p> 动画速度:
<input value="170" max="200" min="1" id="speed" type="range" onchange="srotanimte && srotanimte.changeSpeed(200-this.value)" >
</p>
<p> 数组长度:
<input value="50" width="50" id="arrlen">
<input type="button" value="随即数组" onclick="randomArrayText(document.getElementById('arrlen').value)" class="btn" />
</p>
<p> 待排序数组:
<input id="arrayText" value="[43,27,39,17,32,21,14,42,22,15,18,12,46,1,16,10,4,29,3,23,24,49,0,5,36,13,34,6,19,47,9,33,31,20,28,44,38,37,41,40,8,35,30,7,11,45,2,25,48,26]" style="width:80%;">
</p>
<p></p>
</div>
<div>
<input type="button" value="冒泡排序" onclick="playSortAnimate(sortMethodMap.bubble)" class="btn" />
<input type="button" value="快速排序" onclick="playSortAnimate(sortMethodMap.quick)" class="btn" />
<input type="button" value="插入排序" onclick="playSortAnimate(sortMethodMap.insert)" class="btn" />
<input type="button" value="希尔排序" onclick="playSortAnimate(sortMethodMap.shell)" class="btn" />
<input type="button" value="选择排序" onclick="playSortAnimate(sortMethodMap.selection)" class="btn" />
<input type="button" value="鸡尾酒排序" onclick="playSortAnimate(sortMethodMap.cocktail)" class="btn" />
<input type="button" value="奇偶排序" onclick="playSortAnimate(sortMethodMap.oddEven)" class="btn" />
<input type="button" value="梳排序" onclick="playSortAnimate(sortMethodMap.comb)" class="btn" />
</div>
<div>
<div class="sort-animate-box" id="sortAnimateBox" style="height:100px;"></div>
<div id="sortText"></div>
</div>
</div>
<script type="text/javascript">
var srotanimte = null;
var sortMethodMap = {
bubble:{
sort:"bubbleSort",
animateSort:"bubbleSortAnimate",
text:"冒泡排序"
},
quick:{
sort:"quickSort",
animateSort:"quickSortAnimate",
text:"快速排序"
},
insert:{
sort:"insertSort",
animateSort:"insertSortAnimate",
text:"插入排序"
},
shell:{
sort:"shellSort",
animateSort:"shellSortAnimate",
text:"希尔排序"
},
selection:{
sort:"selectionSort",
animateSort:"selectionSortAnimate",
text:"选择排序"
},
cocktail:{
sort:"cocktailSort",
animateSort:"cocktailSortAnimate",
text:"鸡尾酒排序"
},
oddEven:{
sort:"oddEvenSort",
animateSort:"oddEvenSortAnimate",
text:"奇偶酒排序"
},
comb:{
sort:"combSort",
animateSort:"combSortAnimate",
text:"梳排序"
}
};
function $(id){
return document.getElementById(id);//.value;
}
function getSpeed(){
return 200-document.getElementById('speed').value;
}
function randomArrayText( len ){
len = len || 50;
var arr = [];
for(var i=0; i<len;i++){
arr.push( i );
}
arr.sort(function(){
return Math.random() - 0.5;
});
document.getElementById( "arrayText" ).value = "["+ arr.toString() +"]";
};
function getArray(){
var text = document.getElementById( "arrayText" ).value;
try{
return JSON.parse( text );
}catch(e){
alert("数组有错误")
}
}
function playSortAnimate( key ){
var arr = getArray();
srotanimte = new SortAnimate( arr, $('sortAnimateBox') );
$('sortText').innerHTML = key.text;
window[key.animateSort](arr, srotanimte);
srotanimte.play(getSpeed());
}
//正确性测试
function test(){
var arrays = [
[2,0,1,4,3,5,7,8,6,9],
[2,4,6,0,1,3,8,5,7,9],
[0,6,2,4,3,1,8,5,7,9],
[5,2,0,1,6,7,8,3,4,9],
[0,6,1,2,3,7,8,5,4,9],
[0,2,3,8,5,1,7,6,4,9],
[0,4,1,2,3,6,7,8,9,5],
[0,1],
[1,0],
[0],
[1],
[]
];
console.log("排序正确性测试");
for(var i=0; i<arrays.length; i++){
srotanimte = new SortAnimate( arrays[i], $('sortAnimateBox') );
for(var key in sortMethodMap){
console.log(sortMethodMap[key].text, window[sortMethodMap[key].sort](arrays[i]));
console.log(sortMethodMap[key].text, window[sortMethodMap[key].animateSort](arrays[i], srotanimte));
}
}
console.log("结束");
}
//console.log("选择:",cocktailSort([9,1,3,2,4,6,8,5,0,7], srotanimte));
test();
</script>
</div>
</body>
</html>
css部分:
.column{
width:7px;
height:100%;
background:#cccccc;
display:inline-block;
margin:0 1px;
}
.column:hover{
background:#f30;
}
.active{
background:#888888;
}
.focus{
background:#ffcccc;
}
.highlight{
background:#ff6666;
}
bubble.js部分:
/**
冒泡排序
*/
function bubbleSort(array, srotanimte){
var len = array.length,i,j, d;
for(i=len;i--;){
for(j=0; j<i; j++){
var z = j+1;
if(array[j] > array[z]){
d = array[j];
array[j] = array[z];
array[z] = d;
}
}
}
return array;
};
function bubbleSortAnimate(array, srotanimte){
var len = array.length,i,j, d;
srotanimte.activeFragment(0,len);
for(i=len;i--;){
for(j=0; j<i; j++){
var z = j+1;
srotanimte.activeOne(j);
if(array[j] > array[z]){
d = array[j];
array[j] = array[z];
array[z] = d;
srotanimte.exchange(j, z);
}
srotanimte.blurOne(j);
}
srotanimte.blurFragment(j,len);
}
return array;
};
cocktail.js部分:
/**
鸡尾酒
*/
function cocktailSort(array){
var len = array.length;
var item = array[0];
var i = 0;
var j = len;
var k=0;
var index = 0;
var ischange = false;
while(j - i > 1){
//寻找最大
ischange = false;
item = array[i];
index = i;
for(k=i; k<j; k++){
if(item > array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
}else{
item = array[k];
}
index = k;
}
j--;
//寻找最小
item = array[j];
index = j;
for(k=j; k>i-1; k--){
if(item < array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
}else{
item = array[k];
}
index = k;
}
i++;
//没有任何交换跳出
if( ischange == false ){
break;
}
}
return array;
}
function cocktailSortAnimate(array, srotanimte){
var len = array.length;
var item = array[0];
var i = 0;
var j = len;
var k=0;
var index = 0;
var ischange = false;
while(j - i > 1){
//寻找最大
ischange = false;
item = array[i];
index = i;
srotanimte.activeFragment(i, j);
for(k=i; k<j; k++){
srotanimte.activeOne(k);
if(item > array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
srotanimte.exchange(index, k);
}else{
item = array[k];
}
index = k;
srotanimte.blurOne(k);
}
srotanimte.blurFragment(i, j);
j--;
//寻找最小
item = array[j];
index = j;
srotanimte.activeFragment(i-1, j);
for(k=j; k>i-1; k--){
srotanimte.activeOne(k);
if(item < array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
srotanimte.exchange(index, k);
}else{
item = array[k];
}
index = k;
srotanimte.blurOne(k);
}
srotanimte.blurFragment(i-1, j);
i++;
//没有任何交换跳出
if( ischange == false ){
break;
}
}
return array;
}
comb.js部分:
/**
鸡尾酒
*/
function cocktailSort(array){
var len = array.length;
var item = array[0];
var i = 0;
var j = len;
var k=0;
var index = 0;
var ischange = false;
while(j - i > 1){
//寻找最大
ischange = false;
item = array[i];
index = i;
for(k=i; k<j; k++){
if(item > array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
}else{
item = array[k];
}
index = k;
}
j--;
//寻找最小
item = array[j];
index = j;
for(k=j; k>i-1; k--){
if(item < array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
}else{
item = array[k];
}
index = k;
}
i++;
//没有任何交换跳出
if( ischange == false ){
break;
}
}
return array;
}
function cocktailSortAnimate(array, srotanimte){
var len = array.length;
var item = array[0];
var i = 0;
var j = len;
var k=0;
var index = 0;
var ischange = false;
while(j - i > 1){
//寻找最大
ischange = false;
item = array[i];
index = i;
srotanimte.activeFragment(i, j);
for(k=i; k<j; k++){
srotanimte.activeOne(k);
if(item > array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
srotanimte.exchange(index, k);
}else{
item = array[k];
}
index = k;
srotanimte.blurOne(k);
}
srotanimte.blurFragment(i, j);
j--;
//寻找最小
item = array[j];
index = j;
srotanimte.activeFragment(i-1, j);
for(k=j; k>i-1; k--){
srotanimte.activeOne(k);
if(item < array[k]){
array[index] = array[k];
array[k] = item;
ischange = true;
srotanimte.exchange(index, k);
}else{
item = array[k];
}
index = k;
srotanimte.blurOne(k);
}
srotanimte.blurFragment(i-1, j);
i++;
//没有任何交换跳出
if( ischange == false ){
break;
}
}
return array;
}
insert.js部分
/**
插入排序
*/
function insertSort(array){
var i = 1, j, step, key,
len = array.length;
for(; i < len; i++){
step = j = i;
key = array[j];
while(--j > -1){
if(array[j] > key){
array[j+1] = array[j];
}else{
break;
}
}
array[j+1] = key;
}
return array;
}
function insertSortAnimate(array, srotanimte){
var i = 1, j, step, key,
len = array.length;
for(; i < len; i++){
//srotanimte.activeOne(i);
step = j = i;
key = array[j];
srotanimte.activeFragment(0, i);
while(--j > -1){
srotanimte.activeOne(j);
if(array[j] > key){
srotanimte.exchange(j+1, j);
array[j+1] = array[j];
srotanimte.blurOne(j);
}else{
srotanimte.blurOne(j);
break;
}
srotanimte.blurOne(j);
}
//srotanimte.blurOne(i);
array[j+1] = key;
srotanimte.blurFragment(0, i);
}
return array;
}
oddEven.js部分:
/**
奇偶 金锐提供
*/
function oddEvenSort(list){
var len = list.length;
var sorted = true;
while(sorted){
sorted = false;
for(var i = 1; i < len - 1; i += 2)
{
if(list[i] > list[i + 1])
{
var t = list[i];
list[i] = list[i + 1];
list[i + 1] = t;
sorted = true;
}
}
for(var i = 0; i < len; i += 2){
if(list[i] > list[i + 1]){
var tmp = list[i];
list[i] = list[i + 1];
list[i + 1] = tmp;
sorted = true;
}
}
}
return list;
}
function oddEvenSortAnimate(list, srotanimte){
var len = list.length;
var sorted = true;
while(sorted){
sorted = false;
for(var i = 1; i < len - 1; i += 2)
{
srotanimte.activeOne(i);
srotanimte.activeOne(i+1);
if(list[i] > list[i + 1])
{
var t = list[i];
list[i] = list[i + 1];
list[i + 1] = t;
sorted = true;
srotanimte.exchange(i, i+1);
}
srotanimte.blurOne(i);
srotanimte.blurOne(i+1);
}
for(var i = 0; i < len; i += 2){
srotanimte.activeOne(i);
srotanimte.activeOne(i+1);
if(list[i] > list[i + 1]){
var tmp = list[i];
list[i] = list[i + 1];
list[i + 1] = tmp;
sorted = true;
srotanimte.exchange(i, i+1);
}
srotanimte.blurOne(i);
srotanimte.blurOne(i+1);
}
}
return list;
}
quick.js部分:
/**
快速排序
*/
function quickSort(array){
if(array.length == 0){
return array;
}
var i = 0;
var j = array.length - 1;
var Sort = function(i, j){
// 结束条件
if(i == j ){
return;
};
var key = array[i];
var stepi = i; // 记录开始位置
var stepj = j; // 记录结束位置
while(j > i){
// j <<-------------- 向前查找
if(array[j] >= key){
j--;
}else{
array[i] = array[j]
//i++ ------------>>向后查找
while(j > ++i){
if(array[i] > key){
array[j] = array[i];
break;
}
}
}
}
// 如果第一个取出的 key 是最小的数
if(stepi == i){
Sort(++i, stepj);
return ;
}
// 最后一个空位留给 key
array[i] = key;
// 递归
Sort(stepi, i);
Sort(j, stepj);
}
Sort(i, j);
return array;
}
function quickSortAnimate(array, srotanimte){
if(array.length == 0){
return array;
}
var i = 0;
var j = array.length - 1;
var Sort = function(i, j){
// 结束条件
if(i == j ){
return;
};
srotanimte.activeFragment(i, j)
var key = array[i];
var stepi = i; // 记录开始位置
var stepj = j; // 记录结束位置
//srotanimte.activeOne(i);
while(j > i){
srotanimte.activeOne(j);
// j <<-------------- 向前查找
if(array[j] >= key){
srotanimte.blurOne(j);
j--;
}else{
srotanimte.exchange(i, j);
array[i] = array[j]
//i++ ------------>>向后查找
while(j > ++i){
srotanimte.activeOne(i);
if(array[i] > key){
srotanimte.exchange(i, j);
srotanimte.blurOne(i);
array[j] = array[i];
break;
}
srotanimte.blurOne(i);
}
}
srotanimte.blurOne(j);
}
// 如果第一个取出的 key 是最小的数
srotanimte.blurFragment()
if(stepi == i){
Sort(++i, stepj);
return ;
}
// 最后一个空位留给 key
array[i] = key;
// 递归
Sort(stepi, i);
Sort(j, stepj);
}
Sort(i, j);
return array;
}
selection.js部分:
/**
选择排序
*/
function selectionSort(array){
var len = array.length;
var index = 0;
var k;
var item;
var c;
for(var i=0; i<len; i++){
item = array[i];
index = i;
//寻找最小的数位置
for(j=i+1; j<len;j++){
if(array[j] < item){
index = j;
item = array[j];
}
}
if(index != i){
c = array[i];
array[i] = array[index];
array[index] = c;
}
}
return array;
}
function selectionSortAnimate(array, srotanimte){
var len = array.length;
var index = 0;
var k;
var item;
var c;
for(var i=0; i<len; i++){
item = array[i];
index = i;
srotanimte.activeOne(i);
//寻找最小的数位置
for(j=i+1; j<len;j++){
srotanimte.activeOne(j);
if(array[j] < item){
srotanimte.blurOne(index);
srotanimte.activeOne(j);
index = j;
item = array[j];
}
srotanimte.blurOne(j);
}
srotanimte.blurOne(i);
if(index != i){
srotanimte.blurOne(index);
srotanimte.exchange(i, index);
c = array[i];
array[i] = array[index];
array[index] = c;
}
}
return array;
}
shell.js部分:
/*
希尔
*/
function shellSort(array){
var stepArr = [1031612713, 217378076, 45806244, 9651787, 2034035, 428481, 90358, 19001, 4025, 1750, 836, 701, 301, 132, 57, 23, 10, 4, 1]; // reverse() 在维基上看到这个最优的步长 较小数组
var i = 0;
var stepArrLength = stepArr.length;
var len = array.length;
var len2 = parseInt(len/2);
for(;i < stepArrLength; i++){
if(stepArr[i] > len2){
continue;
}
stepSort(stepArr[i]);
}
// 排序一个步长
function stepSort(step){
//console.log(step) 使用的步长统计
var i = 0, j = 0, f, tem, key;
for(;i < step; i++){// 依次循环列
for(j=1; step * j + i < len; j++){//依次循环每列的每行
tem = f = step * j + i;
key = array[f];
while((tem-=step) >= 0){// 依次向上查找
if(array[tem] > key){
array[tem+step] = array[tem];
}else{
break;
}
}
array[tem + step ] = key;
}
}
}
return array;
}
function shellSortAnimate(array, srotanimte){
var stepArr = [1031612713, 217378076, 45806244, 9651787, 2034035, 428481, 90358, 19001, 4025, 1750, 836, 701, 301, 132, 57, 23, 10, 4, 1]; // reverse() 在维基上看到这个最优的步长 较小数组
var i = 0;
var stepArrLength = stepArr.length;
var len = array.length;
var len2 = parseInt(len/2);
for(;i < stepArrLength; i++){
if(stepArr[i] > len2){
continue;
}
stepSort(stepArr[i]);
}
// 排序一个步长
function stepSort(step){
//console.log(step) 使用的步长统计
var i = 0, j = 0, f, tem, key;
for(;i < step; i++){// 依次循环列
for(j=1; step * j + i < len; j++){//依次循环每列的每行
tem = f = step * j + i;
key = array[f];
srotanimte.activeOne( f );
while((tem-=step) >= 0){// 依次向上查找
//console.log(tem);
srotanimte.activeOne( tem );
if(array[tem] > key){
srotanimte.exchange(tem+step, tem);
array[tem+step] = array[tem];
}else{
srotanimte.blurOne( tem );
break;
}
srotanimte.blurOne( tem );
}
srotanimte.blurOne( f );
array[tem + step ] = key;
}
}
}
return array;
}
SortAnimate.js部分:
/**
记录数组排序过程的步骤
options
*/
function SortAnimate( array, wrapper ){
this.array = array.slice();
this.max = Math.max.apply(Math, array);
this.ui = {columns:[], wrapper:wrapper || document.body};
this.index = -1;
this.animte = [];
this.html = "";
this.init();
};
SortAnimate.prototype = {
init:function(){
var html = "";
for(var i=0; i<this.array.length; i++){
html += this.getColumn(this.array[i], this.array[i]);
}
this.html = html;
this.ui.wrapper.innerHTML = this.html;
this.ui.columns = this.ui.wrapper.getElementsByClassName("column");
},
getHeight:function( number ){
return parseInt(number/this.max*100);
},
getColumn:function( number){
return '+this.getHeight(number)+'%" title="'+ number +'" >';
},
//交换两个数的位置
uiExchange:function( index1, index2 ){
var tmp = this.array[index1];
this.array[index1] = this.array[index2];
this.array[index2] = tmp;
this.uiSetHeight(index1);
this.uiSetHeight(index2);
},
uiSetHeight:function( index ){
var number = this.array[index];
this.ui.columns[index].style.height = this.getHeight( number )+"%";
this.ui.columns[index].title = number;
},
uiHighlightOne:function(index1, index2){
this.ui.columns[index1].className += " highlight";
this.ui.columns[index2].className += " highlight";
},
uiUnHighlightOne:function(index1, index2){
this.ui.columns[index1].className = this.ui.columns[index1].className.replace(" highlight", "");
this.ui.columns[index2].className = this.ui.columns[index2].className.replace(" highlight", "");
},
//激活第 index 个元素
uiActiveOne:function( index ){
this.ui.columns[index].className += " focus";
},
//取消激活 index 个元素
uiBlurOne:function( index ){
this.ui.columns[index].className = this.ui.columns[index].className.replace(" focus", "");
},
//激活数组中一个片段
uiActiveFragment:function(startIndex, endIndex){
//console.log("uiActiveFragment", startIndex, endIndex);
this.startIndex = startIndex;
this.endIndex = endIndex;
for(var i= startIndex; i<endIndex; i++){
this.ui.columns[i].className += " active";
}
},
//取消激活数组中一个片段
uiBlurFragment:function(startIndex, endIndex){
startIndex = startIndex || this.startIndex;
endIndex = endIndex || this.endIndex;
for(var i= startIndex; i<endIndex; i++){
this.ui.columns[i].className = this.ui.columns[i].className.replace(" active","");
}
},
activeOne:function( index ){
this.animte.push({
type:"uiActiveOne",
data:[index]
});
},
blurOne:function( index ){
this.animte.push({
type:"uiBlurOne",
data:[index]
});
},
exchange:function(index1, index2){
this.highlight(index1, index2);
this.unHighlight(index1, index2);
this.animte.push({
type:"uiExchange",
data:[index1, index2]
});
},
activeFragment:function(startIndex, endIndex){
startIndex = startIndex < 0 ? 0 : startIndex;
this.animte.push({
type:"uiActiveFragment",
data:[startIndex, endIndex]
});
},
blurFragment:function(startIndex, endIndex){
startIndex = startIndex < 0 ? 0 : startIndex;
this.animte.push({
type:"uiBlurFragment",
data:[startIndex, endIndex]
});
},
highlight:function( index1, index2 ){
this.animte.push({
type:"uiHighlightOne",
data:[index1, index2]
});
},
unHighlight:function(index1, index2){
this.animte.push({
type:"uiUnHighlightOne",
data:[index1, index2]
});
},
changeSpeed:function( speed ){
this.speed = speed;
this.play();
},
/**
play 播放排序动画
id 容器id
speed 速度单位毫秒
*/
play:function( speed ){
clearInterval( SortAnimate.interid );
this.speed = speed || this.speed;
var animate = this.animte;
var len = animate.length;
var self = this;
SortAnimate.interid = setInterval(function(){
self.index++
if(self.index<len){
self[animate[self.index].type].apply( self, animate[self.index].data);
}else{
clearInterval( SortAnimate.interid );
}
}, this.speed);
}
};