排序算法(冒泡 快速 插入)
2016-07-03 04:31:26

204
冒泡排序
var ary = [5,3,4,2,1];
第一轮:
第1次比较:先用5和3做比较,5大于3那么交换位置之后 [3,5,4,2,1]
第2次比较:由于5和3交换了位置之后,5现在是第二项需要和第三项的4做比较,5是大于4的交换位置 [3,4,5,2,1]
第3次比较: 5仍然是大于2的交换位置 [3,4,2,5,1]
第4次比较: 5和1做比较仍然是大于1交换位置之后 [3,4,2,1,5]分析1:
通过比较发现,这一次虽然没有完成从大到小排序但是却把数组中最大的那个值5放到了数组的最末尾,
5本来是在第一项的位置,一路做比较下来比数组中所有项的值都大,所以默默地站到最后一个的位置上。
这是通过4次循环的做相邻两项比较不断的换位置得出来的结果,但是要注意一点位置交换是有条件的,
只有在做比较的时候是大于的才会做位置交换。分析2:
通过刚才的4次比较不难发现,我们已经成功把数组中的最大值放到了最后位置。那么会想到,如果我
把这个长度为5的数组中的4个最大值依次每次都放到最后的位置上那么也就成功的完成了我的排序工作第二轮:
第1次比较:[3,4,2,1,5]
第2次比较:[3,2,4,1,5]
第3次比较:[3,2,1,4,5]分析3:
经过3次比较之后把4又放到了数组的倒数第2项的位置,如果用一个循环代表轮数,如果数组有5项,
那么只要执行4轮分别把每一轮的最大值放到末尾就可以。那么就是执行length-1轮分析4:
每轮最多比较的次数是:如果用i代表轮数从0开始,用j代表每轮最多比较的次数,那么每轮最多
比较的次数就是lenth-1-i次依次类推第三轮和第四轮结束后分别把3放和2放到4前面的位置上1保持不动达到最终排序效果…
var ary = [5,3,4,2,1];
var posiFlag = false; //用来标记位置上一轮是否发生了位置交换
for(var i=0; i<ary.length-1; i++){
for(var j=0; j<ary.length-1-i; j++){
if(ary[j]>ary[j+1]){ //满足条件做位置交换
posiFlag = true; //现在有位置变化
var temp = ary[j+1]; //位置交换需要借助第三方变量
ary[j+1] = ary[j];
ary[j] = temp;
}
}
if(posiFlag == true){ //在刚刚结束的这一轮有位置变化,下一轮还是有必要的
posiFlag = false;
}else{ //刚刚结束的那一轮就没有人变化位置
break; //如果没有变化位置就没有必要执行下一次循环了
}
}
console.log(ary);
快速排序
var ary = [4,1,2,3,2,1,5];
拿这个简单的数组做例子,先找到一个中间项,然后把这个项目分别和其他项目做比较,比中间项目小的放在左面,比中间项目大的放在右面首先获取中间项目的索引: middleIndex = Math.floor(ary.length/2)
然后通过索引获取中间项: middleItem = ary.splice(middleIndex,1)[0] 这里需要注意下,splice的作用是删除数组,这里两个参数是从middleIndex索引开始删除1项,返回值是删除的数 组项目组成的一个新数组即使只有一个项,也需要用索引0来获取通过比较数组被分成左右两边,被拆分成如下数组,中建项目是3
[1,1,2,2] 3 [4,5]接下来对左边的数组又开始做刚刚的相同的操作,右面也是做相同的操作。
左边:[1,1] 2 [2]
右边:[4] 5 []
一次做这样的操作一直到拆分到数组只有1项或者没有项目为止,如果写成一个函数那么这个函数要一直执行
下去一直到数组项目<=1的时候停止
var ary = [1,2,3,2,1,3];
function quickSort(a){
if(a.length <= 1){
return a; //递归函数,如果每次传入的数组a的长度小于等于1那么就没有必要继续拆分下去了。 这个a形参每次分别代表不同的经过拆分的小数组
}
var middleIndex = Math.floor(a.length/2);
var middleItem = a.splice(middleIndex,1)[0];
var left = [],right = [];
for(var i=0; i<a.length; i++){
a[i] > middleItem ? right.push(a[i]) : left.push(a[i]);
}
return quickSrot(left).concat(middleItem,quickSort(right)); //函数调用函数递归思想,使用 一定要注意停止条件
}
console.log(quickSort(ary));
插入排序
var ary = [4,1,2,3,2,1,5];
先拿这个数组做例子
首先先把第一项4拿出来,然后放到一个新的数组中
那么新数组中只有一个[4],接下来从第二项开始也就是[1,2,3,2,1,5]分别一次拿出来。
第一次拿出来1和新数组中的4做比较,如果大于4就放在4的后面,如果小于4就放在4的前面
重点是如何去比较,加入从新数组中的最后一项去比较[4]=>1。逻辑是这样的如果大于最后一项4那么就插入
到4的后面。如果小于那么就去喝4前面的那一项去比较。但是4前面已经没有项目了。如果索引值已经是0那么就不用去找前面的项了。直接插入到前面就可以了
或者先前找一项之后索引值已经变成-1那么也就直接插入到前面就可以了.
这样就成功的把刚拿来的数组1放到4前面了==> [1,4]下次拿2来做比较的时候,如果找不到合适的位置需要和新数组的每一项都做比较。所以需要一个循环。但是
这个循环是有条件的,如果找到了合适的位置就没有必要继续循环了。否则继续比较下去。如果找到了数组的
终点还没有找到那么就直接插入到最前面就可以了,所以需要注意下过界判断
var ary = [1,2,3,2,1,3];
function insertSrot(ary){
var newAry = [];
newAry.push(ary[0]); //把第一项放到新数组中
for(var i=1; i<ary.length; i++){ //第一项已经拿走了
var curItem = ary[i];
for(var j=newAry.length-1; j>=0; ){
if(curItem<newAry[j]){ //当前项目比数组最后项目小那么需要继续向前查找
j--; //去查找前面的项目
if(j===-1){ //如果j--之后是-1都没有找到合适的位置,那么就直接插入到数组的前面
newAry.unshift(curItem);
}
}else{ //比当前项大,那么就插入到当前数组项目的后面
newAry.splice(j+1,0,curItem);
j=-1; //找到了合适的位置就可以破坏掉循环的条件了
}
}
}
return newAry;
}
console.log(insertSort(ary));