1、冒泡排序
时间复杂度:o(n^2),稳定
- 对未排序的各元素从头到尾依次比较相邻的两个元素大小关系
- 如果左边的队员高, 则两队员交换位置
- 向右移动一个位置, 比较下面两个队员
- 当走到最右端时, 最高的队员一定被放在了最右边
- 按照这个思路, 从最左端重新开始, 这次走到倒数第二个位置的队员即可.
- 依次类推, 就可以将数据排序完成
let arr = [3, 15, 9, 10, 1, 26, 2, 5];
for (let i = 0; i < arr.length - 1; i++) {
for (let j=0; j < arr.length - 1 - i;j++) {
if (arr[j]> arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr); //[1, 2, 3, 5, 9, 10, 15, 26]
2、选择排序
时间复杂度:o(n^2),不稳定
- 选定第一个索引位置,然后和后面元素依次比较
- 如果后面的队员, 小于第一个索引位置的队员, 则交换位置
- 经过一轮的比较后, 可以确定第一个位置是最小的
- 然后使用同样的方法把剩下的元素逐个比较即可
- 可以看出选择排序,第一轮会选出最小值,第二轮会选出第二小的值,直到最后
let arr = [3, 15, 9, 10, 1, 26, 2, 5];
for (let i = 0; i < arr.length - 1; i++) {
let min = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
if (min != i) {
let temp = arr[min];
arr[min] = arr[i];
arr[i] = temp;
}
}
console.log(arr); //[1, 2, 3, 5, 9, 10, 15, 26]
3、插入排序
时间复杂度:o(n^2),稳定
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复上一个步骤,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置后, 重复上面的步骤.
let arr = [3, 15, 9, 10, 1, 26, 2, 5];
for (let i = 0; i < arr.length - 1; i++) {
let j = i + 1;
let temp = arr[j];
while (j > 0 && arr[j - 1] > temp) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
console.log(arr); //[1, 2, 3, 5, 9, 10, 15, 26]
4、希尔排序
时间复杂度:o(n^1.3),不稳定
let arr = [3, 15, 9, 10, 1, 26, 2, 5]
let length = arr.length;
let gap = Math.floor(length / 2); //增量
while (gap >= 1) {
for (let i = 0; i < length - gap; i++) {
let j = i + gap;
let temp = arr[j];
while (j > gap - 1 && arr[j - gap] > temp) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
gap = Math.floor(gap / 2);
}
console.log(arr); //[1, 2, 3, 5, 9, 10, 15, 26]
5、归并排序
时间复杂度:o(nlog2n),稳定
基本思想与过程:先递归的分解数列,再合并数列(分治思想的典型应用)
(1)将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。
(2)按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。
(3)对左右两个小数列重复第二步,直至各区间只有1个数。
下面对数组【42,20,17,13,28,14,23,15】进行归并排序,模拟排序过程如下:
第一步:拆分数组,一共需要拆分三次(logN);
第一次拆成【42,20,17,13】,【28,14,23,15】,
第二次拆成【42,20】,【17,13】,【28,14】,【23,15】,、
第三次拆成【42】,【20】,【17】,【13】,【28】,【14】,【23】,【15】;
第二步:逐步归并数组,采用合并两个有序数组的方法,每一步其算法复杂度基本接近于O(N)
第一次归并为【20,42】,【13,17】,【14,28】,【15,23】
第二次归并为【13,17,20,42】,【14,15,23,28】,
第三次归并为【13, 14, 15, 17, 20, 23, 28, 42】
let arr = [3, 15, 9, 10, 1, 26, 2, 5]
//分数组
function mergeSort() {
arr = merge_1(arr);
console.log(arr)
}
//分数组
function merge_1(arr) {
let length = arr.length;
if (length > 1) {
let index = Math.floor(length / 2);
let left = arr.slice(0, index);
let right = arr.slice(index);
return merge_2(merge_1(left), merge_1(right));
} else {
return arr;
}
}
//合数组
function merge_2(leftArr, rightArr) {
let mergeArr = [];
while (leftArr.length != 0 && rightArr.length != 0) {
if (leftArr[0] > rightArr[0]) {
mergeArr.push(rightArr.shift());
} else {
mergeArr.push(leftArr.shift());
}
}
return mergeArr.concat(leftArr, rightArr);
}
mergeSort()
6、快速排序
时间复杂度:o(nlog2n),不稳定
let arr = [3, 15, 9, 10, 1, 26, 2, 5]
function quickSort() {
arr = quick(arr);
console.log(arr)
}
function quick(arr) {
let length = arr.length;
if (length <= 1) {
return arr;
}
let pivotIndex = Math.floor(length / 2); //找基准下标
let pivot = arr.splice(pivotIndex, 1)[0]; //找基准
let left = [];
let right = [];
for (let i in arr) {
let e = arr[i];
if (e < pivot) {
left.push(e);
} else {
right.push(e);
}
}
return quick(left).concat(pivot, quick(right));
}
quickSort()
7、二分查找
let arr = [1, 2, 3, 5, 9, 10, 15, 26]
function BinarySearch(key) {
let min = 0;
let max = arr.length - 1;
while (min <= max) {
let mid=Math.floor((min + max) / 2);
if (key==arr[mid]) {
return mid;
} else {
if (key < arr[mid]) {
max=mid - 1;
} else { min=mid + 1; }
}
}
return -1;
}
let a=BinarySearch(5);
console.log(a); //3