前言
看这篇文章之前,我们不妨自问一下,我们为什么要去学习算法?这个对我们有什么好处?
- 学习算法可以开拓我们的思维,让我们的逻辑更加严谨
- 学习算法是成为一名优秀的开发者的途径之一
- 可以高质、高效地完成我们业务上的需求
排序算法
冒泡排序
- 依次比较相邻的两个元素,根据大小互换位置,保证每一次比较大的数都在最后
- 重复n+1次,就可完成排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
Array.prototype.bubbleSort = function () { const ctx = this for (let i = 0; i < ctx.length - 1; i++) { for (let j = 0; j < ctx.length - 1 - i; j++) { if (ctx[j] > ctx[j + 1]) { [ctx[j], ctx[j + 1]] = [ctx[j + 1], ctx[j]] } } } }
|
测试:
1 2 3
| let arr = [3, 6, 12, 65, 23, 2] arr.bubbleSort() console.log(arr)
|
选择排序
- 找到数组中最小的值,把它放到第一位,再找到第二小的值,放到第二位
- 重复上次操作n-1次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
Array.prototype.selectionSort = function () { const ctx = this for (let i = 0; i < ctx.length - 1; i++) { let indexMin = i for (let j = i; j < ctx.length; j++) { if (ctx[j] < ctx[indexMin]) { indexMin = j } } if (indexMin !== i) { [ctx[i], ctx[indexMin]] = [ctx[indexMin], ctx[i]] } } }
|
测试:
1 2 3
| let arr = [3, 6, 12, 65, 23, 2] arr.selectionSort() console.log(arr)
|
插入排序
- 从数组第二个数开始往前比较,如它大就往后排
- 依次类推到最后一个数
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
| Array.prototype.insertionSort = function () { const ctx = this if (ctx.length < 1) { return ctx } for (let i = 1; i < ctx.length; i++) { let temp = ctx[i] let j = i while (j > 0) { if (ctx[j - 1] > temp) { [ctx[j - 1], ctx[j]] = [ctx[j], ctx[j - 1]] } else { break } j--; } } }
|
测试:
1 2 3
| let arr = [3, 6, 12, 65, 23, 2] arr.insertionSort() console.log(arr)
|
归并排序
- 把数组劈成两半 在递归的对子数组进行分操作,直到分成一个个单独的数
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
Array.prototype.mergeSort = function () { const ctx = this if (ctx.length <= 1) { return ctx } const recursiveArr = (arr) => { if (arr.length === 1) return arr const indexMid = arr.length >> 1 const leftTemp = arr.slice(0, indexMid) const rightTemp = arr.slice(indexMid) const orderLeft = recursiveArr(leftTemp) const orderRight = recursiveArr(rightTemp) let result = [] while (orderLeft.length || orderRight.length) { if (orderLeft.length && orderRight.length) { result.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight.shift()) } else if (orderLeft.length) { result.push(orderLeft.shift()) } else { result.push(orderRight.shift()) } } return result } const finalResult = recursiveArr(ctx) finalResult.forEach((element, index) => ctx[index] = element) }
|
测试:
1 2 3
| let arr = [3, 6, 12, 65, 23, 2] arr.mergeSort() console.log(arr)
|
合并两个有序链表
- 把两个树合并为有序数组,再对有序数组进行合并, 直到全部子数组合并为一个完整的数组
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 28 29 30 31 32 33 34 35 36
|
const mergeTwoLists = (list1, list2) => { const result = { val: 0, next: null } const p = result const p1 = list1 const p2 = list2 while (p1 && p2) { if (p1.val < p2.val) { p.next = p1 p1 = p1.next } else { p.next = p2 p2 = p2.next } } if (p1) { p1 = p1.next } if (p2) { p2 = p2.next } return result.next }
|
快速排序
- 从数组中任意选择一个基准,比基准小的放在基准前面,比基准大的放在基准后面
- 递归对基准前后的的子数组进行分区
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 28 29 30 31 32 33 34 35
|
Array.prototype.quickSort = function () { const ctx = this if (ctx.length <= 1) { return ctx } const recursive = arr => { if (arr.length <= 1) return arr const benchmark = arr[0] const leftB = [] const rightB = [] for (let i = 1; i < arr.length; i++) { if (arr[i] < benchmark) { leftB.push(arr[i]) } else { rightB.push(arr[i]) } } return [...recursive(leftB), benchmark, ...recursive(rightB)] } const result = recursive(ctx) result.forEach((element, index) => ctx[index] = element) }
|
测试:
1 2 3
| let arr = [3, 6, 12, 65, 23, 2] arr.quickSort() console.log(arr)
|
搜索算法
顺序搜索
- 从头开始搜索数组中的某个元素,比如数组的
indexOf
方法。
二分搜索
- 从数组中的中间位置开始搜索,如果中间元素正好是目标值,则搜索结束
- 如果目标值大于或者小于中间元素,则在大于或者小于中间元素的那一半数组中搜索
- 数组必须是有序的,如不是则需要先进行排序
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 28
|
Array.prototype.binalySearch = function (element) { const ctx = this let minIndex = 0 let maxIndex = ctx.length - 1 while (minIndex <= maxIndex) { let midIndex = (minIndex + maxIndex) >> 1 if (element > ctx[midIndex]) { minIndex = midIndex + 1 } else if (element < ctx[midIndex]) { maxIndex = midIndex - 1 } else { return midIndex } } return -1 }
|
测试:
1 2 3
| const arr = [1, 2, 3, 4, 5, 6] const index = arr.binalySearch(7) console.log(index)
|