最近公司里没有安排什么事情,翻了翻数据结构与算法
这本书,补足一下自己在算法方面的知识。
数组类和方法
es6的出现已经有很长一段时间了,之前看过一些关于es6的教程不过一直没有实践过,这次正好用es6来练练手。
在讲解每一个排序算法前我们先定义一个叫cArray的类和一些方法来辅助我们。
先上代码:
1 | class cArray { |
我们来挨个解释一下。
0. constructor
在constructor里要求传入一个参数表示数组的长度,然后对数组依次赋上默认值。
1. randomSetArr
默认递增的数组显然不是我们想要的,所以这里需要一个方法,把数组每个成员定为随机值。
2. copyArr
如果想要准确比较不同排序算法的速度差异,单一变量原则
很重要,所以我们需要把随机设定的值深拷贝出来,获得多个内容相同又不互相影响的数组。
3. toString
这个就不用解释什么了,把数组成员10个一行地依次输出出来。
4. swap
既然是排序嘛,肯定会有数据成员间互相交换位置的时候
基本排序算法
前戏差不多就这样了,我们来开始正题吧。
数据结构与算法
中说:基本排序算法其核心思想是指对一组数据按照一定的顺序重新排列。重新排列时用到的技术是一组嵌套的for循环。其中,外循环会遍历数组的每一项,内循环则用于比较元素。
冒泡排序
冒泡排序,是最慢的排序之一,也是一种最容易实现的排序算法。
以按升序排列为例,较大的值会浮动到数组的右侧,较小的值会浮动到数组的左侧。
其实就是很简单的数组中两两成员依次比较,如果左大于右,就交换位置。
1 | /** |
我们来试一下这个排序算法的效果,和处理时间:
1 | var numOfElements = 100, |
选择排序
选择排序,从数组的开头开始,将第一个元素和其他元素进行比较。检测完所有元素后,最小的元素会被放到数组的第一个位置,然后算法会从第二个位置继续。这个过程一直进行,当进行到数组的倒数第二个位置时,所有的数据便完成了排序。
1 | selectionSort() { |
接下来是测试时间:
1 | var arr2 = myArray.copyArr(); |
插入排序
插入排序有两个循环。外循环将数组挨个移动,内循环对外循环中选中的元素以及它后面的那个元素进行比较。如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动。插入排序的运行并非通过数据交换,而是通过将较大的数组元素移动到右侧,为数组左侧的较小元素腾出位置。
没有理解到吗?没关系,书上举了一个非常通俗易懂的🌰。
我让班里的每个学生上交一张写有他的名字、学生证号以及个人简介的索引卡片。学生交上来的时候是没有顺序的,但是我想让这些卡片按字母顺序拍好,这样就很容易地与班级花名册进行对照了。
我将卡片带回办公室,清理好书桌,然后拿起第一张卡片,卡片上的姓氏是
Smith
。我把它放到桌子的左上角,然后再拿起第二张卡片,这张卡片上的姓氏是Brown
。我把Smith
移右,把Brown
放到Smith
的前面。 下一张卡片是Williams
,可以把它放到桌面的最右边,而不用移动其他任何卡片。 接下来是Acklin
。这张卡片必须放在这些卡片的最前面,因此其他所有卡片必须向右移动一个位置来为Acklin
这张卡片腾出位置。这就是插入排序的排序原理。
来看代码和运行结果:
1 | insertSort() { |
1 | var arr3 = myArray.copyArr(); |
基本排序算法的计时比较
在上面的运行过程中,我们其实已经在数组长度为100的情况下进行了比较,可以看到这三种算法的执行事件差异并不大。接着我们来分别测试对1k个和10k个数据排序所花时间。
1 | // 长度为1000的情况 |
其实已经渐渐地有些差异了,不过还不大,我们接着增加长度
1 | var numOfElements = 10000; |
小结
10000个数字和1000个数字的测试结果一致,我们可以初步得出:选择排序和插入排序要比冒泡排序快,插入排序是这三种算法中最快的。不过这个结果是基于数据量比较大的时候,较小的数据量并不能比较出这三种排序算法的快慢。
下一次有时间再看看高级排序算法。
以上。