算法
稀疏数组和队列
- 记录数组一共有几行几列,有多少个不同的值,
- 把具有不同值的元素的行列及值记录在一个小规模数组中,减少程序的模型。
排序算法
- 冒泡排序 ( 时间复杂度 : O(n^2) )
function bubble(arr) {
let change = false
for (let i = 0; i < arr.length-1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++){
let t = 0
if(arr[j]>=arr[j+1]){
change = true //优化的地方
t=arr[j]
arr[j] = arr[j+1]
arr[j+1] =t
}
}
if(!change){
break
}else{
change = false
}
}
return arr
}
console.log(bubble(arr))
- 选择排序( 时间复杂度 : O(n^2) ) 介绍:属于内部排序法,是从想要排序的数据中,按指定的规则选出一个元素,再依规定交换位置后达到排序的目的
function selectsort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
let minIndex = i
let min = arr[i]
for (let j = i+1; j < arr.length; j++) {
if (arr[j] < min) {
min = arr[j]
minIndex = j
}
}
if (minIndex !== i) { //这里的意思是 如果经过一轮比较后,最小值
arr[minIndex] = arr[i] //min = arr[i] ,则不需要交换。
arr[i] = min
}
}
return arr
}
console.log(selectsort(arr))
- 插入排序 ( 时间复杂度 : O(n^2) )
介绍:属于内部排序,是对于想要排序的元素以插入的方式找寻该元素适当的位置,以达到排序的目的,
function insertsort(arr) {
for (let i = 1; i < arr.length; i++) {
let insertVal = arr[i]
let insertIndex = i - 1
while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
arr[insertIndex + 1] = arr[insertIndex]
insertIndex--
}
arr[insertIndex + 1] = insertVal
}
return arr
}
console.log(insertsort(arr))
- 希尔排序 ( 时间复杂度 : O(n log n ) )
介绍:希尔排序也是插入排序,他是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。(有两种思路,一种在插入的时候采用交换法,一种采用移动法,其中,移动法的速度最快。)
function shellsort(arr) {
let temp = 0
let j = 0
for (let step = arr.length / 2; step > 0; step = Math.floor(step / 2)) {
for (let i = step; i < arr.length; i++) {
j = i
temp = arr[j]
while (temp < arr[j - step] && j - step >= 0) {
arr[j] = arr[j - step]
j = j - step
}
arr[j] = temp
}
}
return arr
}
console.log(shellsort(arr))
- 快速排序 ( 时间复杂度 : O(n log n ) ) 介绍:是对冒泡排序的改叫。基本思想是通过一趟将要排序的数据分割成独立的两个部分,其中一个部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行。
function quicksort(arr) {
if(arr.length <= 1) return arr
let left = []
let right = []
let pivotIndex = Math.floor(arr.length/2)
let pivot = arr.splice(pivotIndex , 1)[0] //这里是重点,如果改为
//arr[pivotIndex],则会栈溢出报错
for(let i = 0 ; i<arr.length ; i++) {
if(arr[i] < pivot) {
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return [...quicksort(left) , pivot , ...quicksort(right)]
}
console.log(quicksort(arr))
- 归并排序 ( 时间复杂度 : O(n log n ) )
介绍:该算法采用分治策略。而分治,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,再利用递归求解。
function mergeSort(arr) {
if (arr.length < 2) return arr
let mid = Math.floor(arr.length / 2)
let left = arr.slice(0, mid)
let right = arr.slice(mid, arr.length)
return merge(mergeSort(left), mergeSort(right))
}
function merge(left, right) {
let result = []
while (left.length > 0 && right.length > 0) {
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())
}
return result
}
let arr = [1, 4, 7, 1, 5, 3, 0, 15, 47, 20]
console.log(mergeSort(arr))
- 桶排序 ( 时间复杂度 : O(n log n ) )
介绍:将数组分到有限数量的桶里。每个桶再个别排序(可能在使用其他的排序算法),最后依次把各个桶中的记录列出来便得到了有序序列
function binsort(arr, binsize) {
let min = Math.min(...arr)
let max = Math.max(...arr)
let defaultbinsize = 5
binsize = binsize || defaultbinsize
let bincount = Math.floor((max - min) / binsize) + 1
let bin = new Array(bincount)
for (let i = 0; i < bin.length; i++) {
bin[i] = []
}
for (let j = 0; j < arr.length; j++) {
bin[Math.floor((arr[j] - min) / binsize)].push(arr[j]) //这里是最关键的
}
arr.length = 0
for (let i = 0; i < bin.length; i++) {
bin[i].sort((a, b) => a - b)
for (let j = 0; j < bin[i].length; j++) {
arr.push(bin[i][j])
}
}
return arr
}
console.log(binsort(arr))
查找算法
- 二分查找
介绍:二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
- 首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
- 如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
- 如果某一步数组为空,则表示找不到目标元素。
function Tsearch(arr, val) {
if (arr.length == 0) return -1
let left = 0
let right = arr.length - 1
let res = []
while (left <= right) {
let min = parseInt((right + left) / 2)
if (val > arr[min]) {
left = min + 1
} else if (val < arr[min]) {
right = min - 1
} else {
let temp = min - 1
while (true) {
if (temp < 0 || arr[temp] != val) {
break
} else {
res.push(temp)
temp--
}
}
res.push(min)
temp = min + 1
while (true) {
if (temp > right || arr[temp] !== val) {
break
} else {
res.push(temp)
temp++
}
}
return res
}
}
return -1
}
console.log(Tsearch(arr, 400))
- 斐波那契查找 介绍:用斐波那契数列对数组进行分割,也叫做黄金比例分割。
// 先求出一个斐波那契数列
function fbi(len) {
if (len < 0) return -1
let res = []
res[0] = 1
let p = 0
let q = 0
let sum = 1
for (let i = 1; i < len; i++) {
p = q
q = sum
sum = sum + p
res[i] = sum
}
return res
}
// 用斐波那契数列进行分割
function fabonaciiSearch(arr, key) {
let low = 0
let hight = arr.length - 1
let min = 0
let k = 0
let f = fbi(20)
while (hight > f[k] - 1) {
k++
}
let temp = arr
temp.length = f[k]
temp.fill(arr[arr.length - 1], arr.length)
while (low <= hight) {
min = low + f[k - 1] - 1
if (key > arr[min]) {
low = min + 1
k -= 2
} else if (key < arr[min]) {
hight = min - 1
k -= 1
} else {
if (min < hight) {
return min
} else {
return hight
}
}
}
return -1
}
console.log(fabonaciiSearch(arr, 600))
广度优先遍历(BFS)
介绍:从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。
数据结构:队列。
父节点入队,父节点出队列,先左子节点入队,后右子节点入队。递归遍历全部节点即可
let tree = {
value: 0,
chilLeft: {
value: 1,
chilLeft: {
value: 3
},
chilRight: {
value: 4
}
},
chilRight: {
value: 2,
chilLeft: {
value: 5
},
chilRight: {
value: 6
}
}
}
function wid(tree) {
let list = []
let queue = [tree]
while(queue.length !== 0) {
let target = queue.shift()
list.push(target.value)
if(target.chilLeft) {
queue.push(target.chilLeft)
}
if(target.chilRight) {
queue.push(target.chilRight)
}
}
return list
}
//输出结果是 0123456
深度优先遍历(DFS)
介绍:从根节点出发,沿着左子树方向进行纵向遍历,直到找到叶子节点为止。然后回溯到前一个节点,进行右子树节点的遍历,直到遍历完所有可达节点为止。
数据结构:栈
父节点入栈,父节点出栈,先右子节点入栈,后左子节点入栈。递归遍历全部节点即可
let tree = {
value: 0,
chilLeft: {
value: 1,
chilLeft: {
value: 3
},
chilRight: {
value: 4
}
},
chilRight: {
value: 2,
chilLeft: {
value: 5
},
chilRight: {
value: 6
}
}
}
function dep(tree) {
let list = []
let stack = [tree]
while (stack.length !== 0) {
let target = stack.pop()
list.push(target.value)
if (target.chilRight) {
stack.push(target.chilRight)
}
if (target.chilLeft) {
stack.push(target.chilLeft)
}
}
return list
}
//输出结果为 0134256