深入理解各种排序算法

 

### HAHAH

1-------插入排序

这种排序的方法是,举个例子

数组 [ 3,2,5,4,8,7,1] ,这里我们默认用的是从小到大的排序

1   此时数组为 [ 3,2,5,4,8,7,1] ,选出第二项 “2” ,与第一项 “3” 比较,交换位置,数组变成 [ 2,3,5,4,8,7,1] ,此轮比较结束

2   此时数组为 [ 2,3,5,4,8,7,1] ,选出第三项 “5”,与第二项 “3” 进行比较,结果可知,不用交换位置,此轮比较结束

3    此时数组还是为 [ 2,3,5,4,8,7,1] ,选出第四项 “4” ,与第三项 “ 5” 进行比较,两个交换位置,得到数组为  [ 2,3,4,5,8,7,1] ,然后在比较这个新的第三项 "4" 与第二项 “3” ,结果不需要交换,此轮比较到此结束

4   此时数组为 [ 2,3,4,5,8,7,1] ,选出第五项 “8” 与第四项 “ 5” 比较,此时数组不变,此轮结束

5   此时数组还是为 [ 2,3,4,5,8,7,1]  ,选出第六项 “7” 与第五项 “8”比较,交换位置,此时数组为 [ 2,3,4,5,7,8,1]  ,在向前比较 “7”与 “5”,数组不变,此轮结束

6   此时数组为 [ 2,3,4,5,7,8,1]  ,选出最后一项 “1” ,与 “8”比较,交换位置,数组变成 [ 2,3,4,5,7,1,8] ,“1”在向前与“7”比较,再交换,一直比较下去,知道没有可交换的为止。

 这里大家看看这个视频,一清二楚 http://v.youku.com/v_show/id_XMjU4NTY5MzEy.html#paction

怎么用代码来实现呢?

先把这个思路弄清楚,举个例子。还是原来的数组 [ 3,2,5,4,8,7,1]

我们的第一步是选择 “2” ,与“ 3”  比较。 [ 3,2,5,4,8,7,1]

第二步是选择 “5”,与 “3”,“2” 比较 [ 3,2,5,4,8,7,1]

 第三步是“4”,与前面的比较    [ 3,2,5,4,8,7,1]

第四步类推     [ 3,2,5,4,8,7,1]

最后一步  [ 3,2,5,4,8,7,1]

以此类推,那么我们可以定义两层的循环,第一层循环是 2,5,4,8,7,1,第二层循环就是第一层前面的数字。满足条件的时候就交换。这里由于是向前比较,第二层循环的时候,就采用了逆循环。

 function insert(arr) {

  var s;

  for (var i = 1; i < arr.length; i++) {
    for (var j = i; j > 0; j--) {
      if (arr[j] < arr[j - 1]) {
        s=arr[j];
        arr[j]=arr[j-1]
        arr[j-1]=s

             console.log(arr)   //可以打印出来每一个改变的步骤
      }
    }
  }
  return arr
}

console.log(insert([3,3,4,2,1,4,4,3,7,8]))

 

 2-------冒泡排序

这种排序的方法是,举个例子。还是上面的数组 [ 3,2,5,4,8,7,1] 

第一步:选择第一项和第二项,比较,交换位置,数组变成了 [ 2,3,5,4,8,7,1] 

第二步,选择第二项与第三项,比较,还是 [ 2,3,5,4,8,7,1] 

第三步,选择第三项与第四项,比较,交换位置,数组变成了 [ 2,3,4,5,8,7,1] 

以此类推,选择两个相邻的元素,一直比较交换下去。结束第一轮,得到数组 [ 2,3,4,5,7,1,8] ,最后一位 “8” ,是最大的数字,固定不变,

第二轮的遍历,同理,得到 [ 2,3,4,5,1,7,8]  ,最后两位 “7”,“8” 固定下来,进行下一轮

然后类似,一直到排序完成。这里也有一个视频。点击这里

 那怎么用代码来实现呢?我们也是先整理一下思路

 一轮 [ 3,2,5,4,8,7,1], [ 2,3,5,4,8,7,1], [ 2,3,5,4,8,7,1], [ 2,3,4,5,8,7,1] , [ 2,3,4,5,8,7,1], [ 2,3,4,5,7,8,1],[ 2,3,4,5,7,1,8]

二轮  [ 2,3,4,5,7,1,8],[ 2,3,4,5,7,1,8],[ 2,3,4,5,7,1,8],[ 2,3,4,5,7,1,8],[ 2,3,4,5,7,1,8],[ 2,3,4,5,1,7,8]

三轮 [ 2,3,4,5,1,7,8],[ 2,3,4,5,1,7,8],[ 2,3,4,5,1,7,8],[ 2,3,4,5,1,7,8],[ 2,3,4,1,5,7,8]

四轮 [ 2,3,4,1,5,7,8],[ 2,3,4,1,5,7,8],[ 2,3,4,1,5,7,8],[ 2,3,1,4,5,7,8]

五轮[ 2,3,1,4,5,7,8],[ 2,3,1,4,5,7,8],[ 2,1,3,4,5,7,8]

六轮[ 2,1,3,4,5,7,8],[ 1,2,3,4,5,7,8]

七轮[ 1,2,3,4,5,7,8]

这个是我们执行一次的结果,这个就是一个两辆比较的操纵,我们直接一个for循环就可以了

在外面,在套上一个for循环,用来制指定执行的论述,可以看出来,每一轮都是固定一个值,所以轮数就是我们的数组的长度。

我们可以外面定义一个for循环,用来循环轮数,里面写一个for循环,用来比较交换

function bubble(arr) {
        var s
        for (var i =0;i<arr.length;i++) {
            for (var j = 0; j < arr.length; j++) {
                if (arr[j] > arr[j + 1]) {
                    s = arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=s;
                }
            }
        }
        return arr
    }
    console.log(bubble([1,2,3,4,5,7,8]))

3-------选择排序

举例说明,还是数组[ 3,2,5,4,8,7,1] 

这个选择排序思路很简单,就是找出数组中最小的元素,插入到新的数组,并且当前数组删除这个最小项

第一步:[1]   [ 3,2,5,4,8,7] 

第二步:[1,2]   [ 3,5,4,8,7] 

代码思路分析:

先找出数组中的最小项,放入新数组,同时确定这个最小项的索引,根据这个索引,当前数组删除这个最小项

以上的操作,只能进行一次,所以我们在外面加一层的循环,让他执行多次,次数就是数组的长度

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <script type="text/javascript">
    function select(arr) {
        var result = []
        for (var i = 0, len = arr.length; i < len; i++) {
            var min = Math.min.apply(null, arr)
            result.push(min)
            arr.forEach(function(item, index) {
                if (item == min) {
                    arr.splice(index, 1)
                }
            })
        }
        return result
    }
    var arr = [3, 2, 5, 4, 8, 7, 1]]
    var res = select(arr)
    console.log(res)
    </script>
</body>

</html>

 

 4-------快速排序

这个排序的理解要比上面的两个麻烦一点点,还是拿那个数组[ 3,2,5,4,8,7,1]

首先我们先找出一个基准,通常情况下,我们选择的第一个数,也就是“3”当作基准。

第一步 [ 3,2,5,4,8,7,1],这两个橙色的数字出队比较,数字1小于 基准3,两个交换位置,变成 [ 1,2,5,4,8,7,3],数字1归队

第二步 [ 1,2,5,4,8,7,3],数字1归队之后,他的下一个是数字2,出队与基准比较,两个位置不变。数字2归队

第三步 [ 1,2,5,4,8,7,3],数字2归队之后,下一个数字5站出来与基准比较,交换位置,[ 1,2,3,4,8,7,5],数字5归队

第四步 [ 1,2,3,4,8,7,5], 数字5归队之后,他的上一个数字7站出来,与基准比较,没变化,不变

第五步[ 1,2,3,4,8,7,5] 数字8出来比较,不变

第六步[ 1,2,3,4,8,7,5] 数字4出来比较,没变化,但是数字4归队之后,已经没有可以与基准比较的数字了。因此。第一轮结束,基准固定

[ 1,2,3,4,8,7,5],可以看到,基准左边的都小于基准,右边的都比他大。现在第二轮开始

[1,2]出来比较,设置1为基准,2出队比较,位置不变,2回队之后,发现没有继续比较的数字了,因此,基准1固定,2默默的一个人回去。

[8,7,5]基准为8,5出队比较,交换位置,变成[5,7,8] ,5回队之后,7出来比较,位置不变,但是7回去之后,已经没有了可以出来比较的数字,结束。基准固定。数字8位置固定

然后是[5,7],设置基准为5,7出来比较,位置不变,然后7归队之后,发现没有剩下的数字可以与基准比较了,因此,基准固定,数字7默默的归队。

到此,所有的比较就都才是结束了

可以看看这个视频,很清晰的,看这里

同理,怎么用代码来实现了,我们也是先来找找规律。

第一步 [ 3,2,5,4,8,7,1],3,1比较,变成[ 1,2,5,4,8,7,3]

第二步 [ 1,2,5,4,8,7,3],2,3比较,不变

第三步 [ 1,2,5,4,8,7,3],5,3比较,变成[ 1,2,3,4,8,7,5]

第四步[ 1,2,3,4,8,7,5],3,7比较,不变

第五步[ 1,2,3,4,8,7,5],2,8比较,不变

第六步[ 1,2,3,4,8,7,5],3,4比较,此时3的位置确定。分成了两个区间。[ 1,2,3,4,8,7,5]

可以看出来什么规律没有?这个蓝色区域的变化。上面一共有4个蓝色表示的数字分别是1,7,8,4.

再看看橙色的数字,分别是2,5.然后再综合起来看。是不是先蓝色方向的遍历,找到满足的数字,交换之后,

就变成了橙色方向的遍历,橙色也是同理,不满足条件,就一直往前找,知道找到。交换之后,再变成蓝色的遍历方向

因此,我们可以理解为,设置两个指针,first和last.。首先last指向最后一个数字,从这里开始,向前移动,直到找到第一个比基准小的数字。

找到之后,交互位置,last指向下一个位置。再换成first向后移动,找到第一个比基准大的数字。然后交换。first指向下一个位置。再换成last移动,就这样你来我往的移动起来。

那什么时候确定位置呢?

首先,[ 3,2,5,4,8,7,1] ,first用绿色,last用黄色。这里为了观看方便,就只是标记指向

交换之后[ 1,2,5,4,8,7,3],first像前移动。在数字7的位置

然后是last移动了,找到比基准大的数字,也就是数字5,交换之后,first向后移动,得到[ 1,2,3,4,8,7,5],此时first指向数字4的位置。

然后就是last移动了,移动到了数字4的位置,还是没有找到小于基准3的数字。再向前移动,指向数字3的位置,此时变成了这样子[ 1,2,3,4,8,7,5]

黄色跑到了绿色的前面,结束

 

posted @ 2017-09-01 00:50  阿柴与米  阅读(599)  评论(0编辑  收藏  举报