先上一张耳熟能详的图
n: 数据规模
k:“桶”的个数
In-place: 占用常数内存,不占用额外内存
Out-place: 占用额外内存
稳定性:排序后2个相等键值的顺序和排序之前它们的顺序相同
时间复杂度:o(1)
1、冒泡排序
前后两个数据对比,找出较大的值并交换位置,继续向后比较最后找出最大的值;
内层循环一次,找出一个最大值,当找到倒数第二大的值得时候,循环结束。
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { //相邻元素两两对比
var temp = arr[j+1]; //元素交换
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
2、选择排序
用最开始的数据和所有的数据作比较,得到最小的数,依次循环找到每次循环最小的数。即可得到升序的数据。
function selectionSort(arr) {
var len = arr.length;
var minIndex, temp;
for (var i = 0; i < len - 1; i++) {
minIndex = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { //寻找最小的数
minIndex = j; //将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
3、快速排序
快速排序采取了分而治之的思想,有点二分法的意思。
简而言之,取一个中间值,大于中间值的放在右边,小于的放在左边,然后依次循环左右两边的数组继续取中间值作比较,直至排序完成,拼接即可。
var quickSort = function(arr) {
if (arr.length <= 1) { return arr; }
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
};
quickSort([3, 2, 4, 5, 1]);
4、插入排序
function insertionSort(arr) {
var len = arr.length;
var preIndex, current;
for (var i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current) {
//这一个循环的含义:当前的元素和数组中下标小于它的元素作对比,如果当前元素大于,则位置不变,小于的话继续比较,然后找到大于的位置插入进去
arr[preIndex+1] = arr[preIndex];
preIndex--;
}
arr[preIndex+1] = current;
}
return arr;
}
二分法插入排序
function binaryInsertionSort(array) {
for (var i = 1; i < array.length; i++) {
var key = array[i], left = 0, right = i - 1;
while (left <= right) {//当数据不进入这个循环的时候,就说明left大于right,也就说明key的值介于left和right之间
var middle = parseInt((left + right) / 2);
if (key < array[middle]) {
right = middle - 1;
} else {
left = middle + 1;
}
}
for (var j = i - 1; j >= left; j--) {//由于上一步的操作导致left和right的位置交换,所以我们以left之前作为插入可以的位置,所以left以后的数据需要后移
array[j + 1] = array[j];
}
array[left] = key;//left以后的数据后移一位后,就可以将key放在left的位置了。
}
return array;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
仔细看说明,就能明白其中的意思。
function shellSort(arr) {
var len = arr.length,
temp,
gap = 1;
while(gap < len/5) { //动态定义间隔序列
gap =gap*5+1;
console.log(gap);
}
for (gap; gap > 0; gap = Math.floor(gap/5)) {
for (var i = gap; i < len; i++) {
temp = arr[i];
for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
console.log(arr);
}
return arr;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48,77,64];
console.log(shellSort(arr));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50];
数据分组比较
6、归并排序
主要的思想是把数组拆分成小的数组,然后小数据进行比较,将比较后的值按顺序放在一个空数组里
function mergeSort(arr) { //采用自上而下的递归方法,用来拆分数据成小的数组
var len = arr.length;
if(len < 2) {
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right){
var result = [];
console.time('归并排序耗时');
while (left.length && right.length) {
if (left[0] <= right[0]) {//对比左右的数据,小的数据先进栈
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length){
result.push(left.shift());
}
while (right.length){
result.push(right.shift());
}
console.timeEnd('归并排序耗时');
return result;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(mergeSort(arr));
7、堆排序
function heapSort(array) {
console.time('堆排序耗时');
//建堆
var heapSize = array.length, temp;
for (var i = Math.floor(heapSize / 2) - 1; i >= 0; i--) {
heapify(array, i, heapSize);
}
//堆排序
for (var j = heapSize - 1; j >= 1; j--) {
temp = array[0];
array[0] = array[j];
array[j] = temp;
console.log(array)
heapify(array, 0, --heapSize);
}
console.timeEnd('堆排序耗时');
return array;
}
function heapify(arr, x, len) {
var l = 2 * x + 1, r = 2 * x + 2, largest = x, temp;
if (l < len && arr[l] > arr[largest]) {
largest = l;
}
if (r < len && arr[r] > arr[largest]) {
largest = r;
}
if (largest != x) {
temp = arr[x];
arr[x] = arr[largest];
arr[largest] = temp;
console.log(arr)
heapify(arr, largest, len);
}
}
var arr=[91,60,96,13,35,65,46,65,10,30,20,31,77,81,22];
console.log(heapSort(arr));//[10, 13, 20, 22, 30, 31, 35, 46, 60, 65, 65, 77, 81, 91, 96];
8、计数排序
9、桶排序
10、基数排序