JavaScript版各大排序算法

排序算法的设计与实现

这是一个可视化的排序展示,支持冒泡、插入和选择排序,具体使用先 随机添加40个,然后点排序,就可以看到可视化的效果。
推荐一下,HTML5 Canvas Demo:Sorting Algorithms,这里还有个可视化的排序博客,各大排序算法的实现都栩栩如生。

JavaScript写排序算法主要是参数问题,比如JavaScript算法函数可以扔给Array原型:Array.prototype.sort = function,也可以直接写个函数带参数:function sort(array) {},哪种方法都一样,需要注意的是兼容性问题,如果可以考虑所有可遍历对象都能排序(比如argument),才大法好!
下面的排序都是从小到大的排序:

插入排序

插入排序是一种基本排序,它的基本思路是构建有序序列,对于未排序的数据,在已排序的基础上,从右向左(或者二分查找)选择位置插入。

1
2
3
4
5
6
7
8
9
10
11
function insert_sort(input) {
var i, j, temp;
for(i = 0; i < input.length; i++){
temp = input[i];
for(j = i-1; j >= 0 && input[j] > temp; j--) {
input[j+1] = input[j];
}
input[j+1] = temp;
}
return input;
}

如果以比较次数和移动次数来衡量算法的效率,最好的情况下,比较n-1次,移动0次,最坏情况,比较n(n-1)/2次,移动n(n-1)/2次。

二分插入排序

思路基本与插入算法相同,只是在查找插入位置的时候,不是依次查找,而是采用二分法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function bin_insert_sort(input) {
var i, j, low, mid, high, temp;
for(i = 0; i < input.length; i++) {
temp = input[i];
high = i - 1;
low = 0;
while(low <= high) {
min = parseInt((low + high)/2);
if(temp < input[mid]) {
high = mid - 1;
}else {
low = mid + 1;
}
}
// low的位置就是要插入的位置
for(j = i - 1; j >= low; j--) {
input[j+1] = input[j]
}
input[low] = temp;
}
return input;
}

希尔排序

希尔排序其实是加强版的插入排序,就是在原先的插入排序的基础上,加入了步长,原先插入排序的步长是1,而且步长不同,效率也有差异,选择一个合适的步长也很重要。而且,希尔排序的最后一步,也必定是步长为1的插入排序,只不过此时整个排序已经基本稳定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function shell_sort(input) {
var gap, i, j, temp;
gap = input.length >> 1;
while(gap > 0) {
for(i = gap; i < input.length; i++) {
temp = input[i];
for(j = i - gap;j >= 0 && input[j] > temp; j -= gap) {
input[j + gap] = input[j];
}
input[j + gap] = temp;
}
gap = gap >> 1;
}
return input;
}

选择排序

选择排序的工作原理:首先在未排序序列中找到最小(大)元素,存放在排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function select_sort(input) {
var i, j, min, temp;
for(i = 0; i < input.length - 1; i++) {
min = i;
for(j = i + 1; j < input.length; j++) {
if(input[min] > input[j]) {
min = j;
}
}
temp = input[min];
input[min] = input[i];
input[i] = temp;
}
return input;
}

选择排序在最好的情况下和最坏的情况下,比较次数是一样的,都是n*(n-1)/2;

冒泡排序

冒泡排序的原理:对于待排序列,它会遍历多次,每次都会比较相邻的两个元素,若顺序相反,即交换他们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function bubble_sort(input) {
var i, j, temp, flag;
for(i = 0; i < input.length - 1; i++) {
flag = true;
for(j = 0; j < input.length - i; j++) {
if (input[j] > input[j + 1]) {
temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
flag = false;
}
}
if (flag) {
break;
}
}
return input;
}

有flag时,最好的情况比较n-1次,移动0次,最坏情况,比较n(n-1)/2次,交换n(n-1)/2

快排

快排的基本思路就是选择一个元素,然后按照与这个元素的比较,将大于这个元素的都拿到右边,小于这个元素的都拿到左边,并找到这个元素的位置这个元素的左右两边递归。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function quick_sort (input) {
function sort(start, end) {
if (start >= end) {
return;
}
var mid = partition(start, end);
sort(start, mid - 1);
sort(min + 1, end);
}
function partition(start, end) {
var left = start, right = end, key = input[start], temp;
while(left < right) {
while(left < right && input[right] >= key) {
right--;
}
input[left] = input[right];
while(left < right && input[left] <= key){
left++
}
input[right] = input[left];
}
input[left] = key;
return left;
}
sort(0, input.length - 1);
return input;
}

关于快排的详解