这五个排序也算是耳熟能详的了,不过自己一直也是只懂原理,用js还没实现过,所以留下一点笔记,来记录下这五种基本算法,不过网上有很多,我也只是把自己的实现写了下来。
冒泡排序
//冒泡排序, 稳定的排序方式,平均时间O(n^2)
function bubble(a) {
var l = a.length;
for (var i = 0; i < l - 1; i++) {
for (var j = 0; j < l - 1 - i; j++) {
if (a[j] > a[j + 1]) {
var temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
return a;
}
最基本的算法,当初学C的时候接触的第一个排序方式,两个数之间比较,大的后移,小的前浮,就想水里的泡泡,不过自己一直会把冒泡和简单选择弄混掉,之前笔试的时候还写错了,不过当时没被发现这个错误还一度以为我的冒泡是写对的,其实写了很久的所谓冒泡都是选择排序。
选择排序
//选择排序,不稳定的排序方式,时间复杂度O(n^2)
function select(a) {
var l = a.length;
for (var i = 0; i < l - 1; i++) {
var temp = a[i];
for (var j = i + 1; j < l; j++) {
if (a[i] > a[j]) {
var t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
return a;
}
思路很简单,就是每次都把之后最小的找出来,然后和当前位置的数字进行交换,之前无数次以为这就是冒泡…
插入排序
//插入排序, 稳定的排序,时间复杂度O(n^2)
function insert(a) {
var l = a.length,
nowPos = 0, //已排序数组部分的最后一位
key = 0; //当前需要插入的元素
for (var i = 1; i < l; i++) {
if(a[i] >= a[i-1]) continue;
nowPos = i - 1;
key = a[i];
a[i] = a[nowPos]; //把已排序数组的长度扩大一位,用已排序的最后一位填补
while(nowPos-- >= 0) { //找到可以插入的位置
if(key < a[nowPos]) { //把比当前元素大的都向后移
a[nowPos + 1] = a[nowPos];
} else break
}
a[nowPos + 1] = key;
}
return a;
}
插入排序把原数组分成两个部分,一部分是已排序的,一部分是未排序的,每次都从未排序的里面从前往后拿一个插到已排序数组中恰当的位置。
归并排序
//归并排序,稳定的排序方式,时间复杂度O(nlogn)
//自顶向下,采用分治的思想
function merge(left, right) {
var result = [];
while (left.length > 0 && right.length > 0) {
if (left[0] > right[0]) {
result.push(right.shift());
} else {
result.push(left.shift())
}
}
return result.concat(left).concat(right);
}
function mergeSort(arr) {
if (arr.length <= 1) return arr; //递归出口
var mid = Math.floor(arr.length / 2); //数组中间位置
var left = arr.slice(0, mid), //左半边的数组
right = arr.slice(mid); //右半边的数组
return merge(mergeSort(left), mergeSort(right))
}
这个算法在上算法课的时候有讲过,就是把一个数组对半分,然后再对半分,一直分到不可分为止,然后对分得的每一小个数组进行排序,然后再组合到一起,典型的分治思想,好像分治里面最会的也就只有这一个算法了…
快速排序
//快速排序, 不稳定的排序,时间复杂度O(nlogn)
function quickSort(a) {
if (a.length <= 1) return a;
var mid = Math.floor(a.length / 2);
var midVal = a.splice(mid, 1);
var left = [], right = [];
for (var i = 0; i < a.length; i++) {
if (a[i] < midVal) {
left.push(a[i]);
} else {
right.push(a[i]);
}
}
// var l = quickSort(left);
// var r = quickSort(right);
// return l.concat(midVal, r);
return quickSort(left).concat(midVal, quickSort(right))
}
快速排序,听名字就很快,也是如同归并把数组分成几部分,不过不同的是,这个例子的快速排序中将中间的元素作为基准,然后把比它小的放到一个数组里,比它大的放到一个数组里,然后再如此反复,最后将所有的整合起来。我本以为这个和归并差不多,其实还是差很多的,但是差在哪里也说不出来,反正看起来就差很多-。-
除了这五种算法以外还有好多,不过就不一一描述了,这五种基本算法算是必须掌握的吧,特此记录下,免得下次再忘。