快速排序相对于其他排序效率更高的原因
上面一共提到了 8 种排序的方法,在实际使用中,应用最广泛的是快速排序。快速排序相对于其他排序算法的优势在于在相同数据量的情况下,它的运算效率最高,并且它额外所需空间最小。
我们首先从时间复杂度来判断,由于前面几种方法的时间复杂度平均情况下基本趋向于 O(n²),因此只从时间复杂度上来看的话,显然归并排序、堆排序和快速排序的时间复杂度最小。但是既然这几种方法的时间复杂度基本一致,并且快速排序在最坏情况下时间的复杂度还会变为 O(n²),那么为什么它的效率反而更高呢?
首先在对大数据量排序的时候,由于归并排序的空间复杂度为 O(n),因此归并排序在这种情况下会需要过多的额外内存,因此归并排序首先就被排除掉了。
接下来就剩下了堆排序和快速排序的比较。我认为堆排序相对于快速排序的效率不高的原因有两个方面。
第一个方面是对于比较操作的有效性来说。对于快速排序来说,每一次元素的比较都会确定该元素在数组中的位置,也就是在枢纽值的左边或者右边,快速排序的每一次比较操作都是有意义的结果。而对于堆排序来说,在每一次重新调整堆的时候,我们在迭代时,已经知道上层的节点值一定比下层的节点值大,因此当我们每次为了打乱堆结构而将最后一个元素与堆顶元素互换时,互换后的元素一定是比下层元素小的,因此我们知道比较结果却还要在堆结构调整时去进行再一次的比较,这样的比较是没有意义的,以此在堆排序中会产生大量的没有意义的比较操作。
第二个方面是对于缓存局部性原理的利用上来考虑的,我认为这应该是造成堆排序的效率不如快速排序的主要原因。在计算机中利用了多级缓存的机制,来解决 cpu 计算速度与存储器数据读取速度间差距过大的问题。缓存的原理主要是基于局部性原理,局部性原理简单来说就是,当前被访问过的数据,很有可能在一段时间内被再次访问,这被称为时间局部性。还有就是当前访问的数据,那么它相邻的数据,也有可能在一段时间内被访问到,这被称为空间局部性。计算机缓存利用了局部性的原理来对数据进行缓存,来尽可能少的减少磁盘的 I/O 次数,以此来提高执行效率。对于堆排序来说,它最大的问题就是它对于空间局部性的违背,它在进行比较时,比较的并不是相邻的元素,而是与自己相隔很远的元素,这对于利用空间局部性来进行数据缓存的计算机来说,它的很多缓存都是无效的。并且对于大数据量的排序来说,缓存的命中率就会变得很低,因此会明显提高磁盘的 I/O 次数,并且由于堆排序的大量的无效比较,因此这样就造成了堆排序执行效率的低下。而相对来快速排序来说,它的排序每一次都是在相邻范围内的比较,并且比较的范围越来越小,它很好的利用了局部性原理,因此它的执行效率更高。简单来说就是在堆排序中获取一个元素的值所花费的时间比在快速排序获取一个元素的值所花费的时间要大。因此我们可以看出,时间复杂度类似的算法,在计算机中实际执行可能会有很大的差别,因为决定算法执行效率的还有内存读取这样的其他的因素。