编程能力之排序

不稳定排序 “快些选堆”

一些结论
(1)时间复杂度,快速排序、希尔排序、归并排序、堆排序的平均时间为O(nlogn),其他的为O(n*n)。算法log大部分指log2(x)啦
(2)快速排序、希尔排序、选择排序、堆排序不稳定,其他的稳定。
(3)经过一趟排序能够保证一个元素到达最终位置的是冒泡排序、快速排序、选择排序、堆排序。
(4)元素比较次数和原始序列无关的是选择排序、折半插入排序。
(5)排序趟数和原始序列有关的是交换类排序。
(6)直接插入排序和折半插入排序的区别是寻找插入位置的方式不同,一个是按顺序查找方式,另一个是按折半查找方式。

图解方面我就不班门弄斧了,发链接 GIF演示排序算法

还有一个在很多地方都见过的俄罗斯方块一样的视觉直观感受 7 种常用的排序算法

排序算法分类
1、插入类排序
即在一个已经有序的序列中,插入一个新的记录,就好比军训排队,已经排好一个纵队,这时来了个新家伙,于是新来的“插入”这个队伍中的合适位置。这类排序有:直接插入排序、折半插入排序、希尔排序。
2、交换类排序
该类方法的核心是“交换”,即每趟排序,都是通过一系列的“交换”动作完成的,如军训排队时,教官说:你比旁边的高,你俩交换下,还比下一个高就继续交换。这类排序有:冒泡排序、快速排序。
3、选择类排序
该方法的核心是“选择”,即每趟排序都选出一个最小(或最大)的记录,把它和序列中的第一个(或最后一个)记录交换,这样最小(或最大)的记录到位。如军训排队时,教官选出个子最小的同学,让他和第一个位置的同学交换,剩下的继续选择。这类排序有:选择排序、堆排序。
4、归并类排序
所谓归并,就是将两个或两个以上的有序序列合并成一个新的有序序列。如军训排队时,教官说:每个人先和旁边的人组成二人组,组内排好队,二人组和旁边的二人组组成四人组,内部再排好队,以此类推,直到最后全部同学都归并到一个组中并排好序。这类排序有:(二路)归并排序。
5、基数类排序
此类方法较为特别,是基于多关键字排序的思想,把一个逻辑关键字拆分成多个关键字,如一副扑克牌,按照基数排序思想可以先按花色排序,则分成4堆,每堆再按A-K的顺序排序,使得整副扑克牌最终有序。

交换算法
由于大部分排序算法中使用到两个记录相互交换的动作,因此将交换动作单独封装出来,便于各排序算法使用。
//交换函数
Array.prototype.swap = function(i, j) {
var temp = this[i];
this[i] = this[j];
this[j] = temp;
}

插入排序是在以排序的基础上再排序,介绍意义不大

希尔是在插入基础上的白话经典算法系列之三 希尔排序的实现


冒泡排序
算法思想:通过一系列的“交换”动作完成的,首先第一个记录与第二个记录比较,如果第一个大,则二者交换,否则不交换;然后第二个记录和第三个记录比较,如果第二个大,则二者交换,否则不交换,以此类推,最终最大的那个记录被交换到了最后,一趟冒泡排序完成。在这个过程中,大的记录就像一块石头一样沉底,小的记录逐渐向上浮动。冒泡排序算法结束的条件是一趟排序没有发生元素交换。
//冒泡排序
Array.prototype.bubbleSort = function() {
for (var i = this.length - 1; i > 0; --i)
{
for (var j = 0; j < i; ++j)
if (this[j] > this[j + 1])
this.swap(j, j + 1);
}
}


快速排序
算法思想:以军训排队为例,教官说以第一个同学为中心,比他矮的站他左边,比他高的站他右边,这就是一趟快速排序。因此,一趟快速排序是以一个枢轴,将序列分成两部分,枢轴的一边比它小(或小于等于),另一边比它大(或大于等于)。
//递归快速排序
Array.prototype.quickSort = function(s, e) {
if (s == null)
s = 0;
if (e == null)
e = this.length - 1;
if (s >= e)
return;
this.swap((s + e) >> 1, e);
var index = s - 1;
for (var i = s; i <= e; ++i)
if (this[i] <= this[e]) this.swap(i, ++index);
this.quickSort(s, index - 1);
this.quickSort(index + 1, e);
}
算法性能:快速排序最好情况下时间复杂度为O(nlogn),待排序列越接近无序,则该算法效率越高,在最坏情况下时间复杂度为O(n*n),待排序列越接近有序,则该算法效率越低,算法的平均时间复杂度为O(nlogn)。就平均时间而言,快速排序是所有排序算法中最好的。该算法的空间复杂度为O(logn),快速排序是递归进行的,需要栈的辅助,因此需要的辅助空间比前面几类排序方法要多。


选择排序
算法思想:该算法的主要动作就是“选择”,采用简单的选择方式,从头至尾顺序扫描序列,找出最小的一个记录,和第一个记录交换,接着从剩下的记录中继续这种选择和交换,最终使序列有序。
//选择排序
Array.prototype.selectionSort = function() {
for (var i = 0; i < this.length; ++i)
{
var index = i;
for (var j = i + 1; j < this.length; ++j)
{
if (this[j] < this[index])
index = j;
}
this.swap(i, index);
}
}
算法性能:将最内层循环中的比较视为基本操作,其执行次数为(n-1+1)*(n-1)/2=n(n-1)/2,其时间复杂度为O(n*n),本算法的额外空间只有一个temp,因此空间复杂度为O(1)。

这里再谈谈《算法》第四版



猜你喜欢

转载自blog.csdn.net/ation_work/article/details/66478900
今日推荐